@jbrowse/plugin-alignments 2.4.2 → 2.6.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 (443) hide show
  1. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +2 -2
  2. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureFlags.d.ts +2 -2
  3. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureFlags.js +2 -1
  4. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureFlags.js.map +1 -1
  5. package/dist/AlignmentsFeatureDetail/AlignmentsFeatureSuppAligns.d.ts +2 -2
  6. package/dist/AlignmentsFeatureDetail/index.d.ts +4 -1
  7. package/dist/AlignmentsTrack/configSchemaF.d.ts +74 -0
  8. package/dist/AlignmentsTrack/configSchemaF.js +19 -0
  9. package/dist/AlignmentsTrack/configSchemaF.js.map +1 -0
  10. package/dist/AlignmentsTrack/index.js +2 -15
  11. package/dist/AlignmentsTrack/index.js.map +1 -1
  12. package/dist/BamAdapter/BamAdapter.d.ts +2 -2
  13. package/dist/BamAdapter/BamAdapter.js +27 -32
  14. package/dist/BamAdapter/BamAdapter.js.map +1 -1
  15. package/dist/BamAdapter/BamSlightlyLazyFeature.d.ts +1 -1
  16. package/dist/BamAdapter/configSchema.d.ts +50 -1
  17. package/dist/CramAdapter/CramAdapter.d.ts +1 -1
  18. package/dist/CramAdapter/CramAdapter.js +49 -47
  19. package/dist/CramAdapter/CramAdapter.js.map +1 -1
  20. package/dist/CramAdapter/CramSlightlyLazyFeature.js +3 -5
  21. package/dist/CramAdapter/CramSlightlyLazyFeature.js.map +1 -1
  22. package/dist/CramAdapter/CramTestAdapters.js +3 -3
  23. package/dist/CramAdapter/CramTestAdapters.js.map +1 -1
  24. package/dist/CramAdapter/configSchema.d.ts +40 -1
  25. package/dist/HtsgetBamAdapter/configSchema.d.ts +26 -1
  26. package/dist/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
  27. package/dist/LinearAlignmentsDisplay/models/configSchema.d.ts +39 -1
  28. package/dist/LinearAlignmentsDisplay/models/model.d.ts +20 -6
  29. package/dist/LinearAlignmentsDisplay/models/model.js +9 -4
  30. package/dist/LinearAlignmentsDisplay/models/model.js.map +1 -1
  31. package/dist/LinearPileupDisplay/components/ColorByModifications.d.ts +2 -2
  32. package/dist/LinearPileupDisplay/components/ColorByModifications.js +3 -23
  33. package/dist/LinearPileupDisplay/components/ColorByModifications.js.map +1 -1
  34. package/dist/LinearPileupDisplay/components/ColorByTag.d.ts +2 -2
  35. package/dist/LinearPileupDisplay/components/ColorByTag.js +2 -6
  36. package/dist/LinearPileupDisplay/components/ColorByTag.js.map +1 -1
  37. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +3 -3
  38. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +6 -6
  39. package/dist/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js.map +1 -1
  40. package/dist/LinearPileupDisplay/components/ModificationsTable.d.ts +4 -0
  41. package/dist/LinearPileupDisplay/components/ModificationsTable.js +29 -0
  42. package/dist/LinearPileupDisplay/components/ModificationsTable.js.map +1 -0
  43. package/dist/LinearPileupDisplay/components/SetFeatureHeight.d.ts +2 -2
  44. package/dist/LinearPileupDisplay/components/SetMaxHeight.d.ts +2 -2
  45. package/dist/LinearPileupDisplay/components/SetMaxHeight.js +3 -5
  46. package/dist/LinearPileupDisplay/components/SetMaxHeight.js.map +1 -1
  47. package/dist/LinearPileupDisplay/components/SortByTag.d.ts +2 -2
  48. package/dist/LinearPileupDisplay/configSchema.d.ts +57 -1
  49. package/dist/LinearPileupDisplay/model.d.ts +160 -80
  50. package/dist/LinearPileupDisplay/model.js +181 -138
  51. package/dist/LinearPileupDisplay/model.js.map +1 -1
  52. package/dist/LinearReadArcsDisplay/components/ReactComponent.d.ts +2 -2
  53. package/dist/LinearReadArcsDisplay/components/ReactComponent.js +36 -39
  54. package/dist/LinearReadArcsDisplay/components/ReactComponent.js.map +1 -1
  55. package/dist/LinearReadArcsDisplay/configSchema.d.ts +59 -1
  56. package/dist/LinearReadArcsDisplay/drawFeats.d.ts +2 -15
  57. package/dist/LinearReadArcsDisplay/drawFeats.js +58 -66
  58. package/dist/LinearReadArcsDisplay/drawFeats.js.map +1 -1
  59. package/dist/LinearReadArcsDisplay/model.d.ts +58 -193
  60. package/dist/LinearReadArcsDisplay/model.js +65 -115
  61. package/dist/LinearReadArcsDisplay/model.js.map +1 -1
  62. package/dist/LinearReadArcsDisplay/util.d.ts +2 -0
  63. package/dist/LinearReadArcsDisplay/util.js +13 -0
  64. package/dist/LinearReadArcsDisplay/util.js.map +1 -0
  65. package/dist/LinearReadCloudDisplay/components/ReactComponent.d.ts +2 -2
  66. package/dist/LinearReadCloudDisplay/components/ReactComponent.js +34 -36
  67. package/dist/LinearReadCloudDisplay/components/ReactComponent.js.map +1 -1
  68. package/dist/LinearReadCloudDisplay/configSchema.d.ts +52 -1
  69. package/dist/LinearReadCloudDisplay/drawFeats.d.ts +2 -10
  70. package/dist/LinearReadCloudDisplay/drawFeats.js +11 -127
  71. package/dist/LinearReadCloudDisplay/drawFeats.js.map +1 -1
  72. package/dist/LinearReadCloudDisplay/drawLongReadChains.d.ts +11 -0
  73. package/dist/LinearReadCloudDisplay/drawLongReadChains.js +69 -0
  74. package/dist/LinearReadCloudDisplay/drawLongReadChains.js.map +1 -0
  75. package/dist/LinearReadCloudDisplay/drawPairChains.d.ts +17 -0
  76. package/dist/LinearReadCloudDisplay/drawPairChains.js +100 -0
  77. package/dist/LinearReadCloudDisplay/drawPairChains.js.map +1 -0
  78. package/dist/LinearReadCloudDisplay/model.d.ts +65 -196
  79. package/dist/LinearReadCloudDisplay/model.js +55 -92
  80. package/dist/LinearReadCloudDisplay/model.js.map +1 -1
  81. package/dist/LinearReadCloudDisplay/util.d.ts +2 -0
  82. package/dist/LinearReadCloudDisplay/util.js +35 -0
  83. package/dist/LinearReadCloudDisplay/util.js.map +1 -0
  84. package/dist/LinearSNPCoverageDisplay/components/Tooltip.d.ts +2 -2
  85. package/dist/LinearSNPCoverageDisplay/models/configSchema.d.ts +79 -1
  86. package/dist/LinearSNPCoverageDisplay/models/model.d.ts +157 -70
  87. package/dist/LinearSNPCoverageDisplay/models/model.js +46 -33
  88. package/dist/LinearSNPCoverageDisplay/models/model.js.map +1 -1
  89. package/dist/MismatchParser/index.d.ts +7 -2
  90. package/dist/MismatchParser/index.js +44 -5
  91. package/dist/MismatchParser/index.js.map +1 -1
  92. package/dist/PileupRPC/methods/GetReducedFeatures.d.ts +15 -2
  93. package/dist/PileupRPC/methods/GetReducedFeatures.js +1 -8
  94. package/dist/PileupRPC/methods/GetReducedFeatures.js.map +1 -1
  95. package/dist/PileupRenderer/PileupLayoutSession.d.ts +1 -1
  96. package/dist/PileupRenderer/PileupRenderer.d.ts +4 -117
  97. package/dist/PileupRenderer/PileupRenderer.js +18 -752
  98. package/dist/PileupRenderer/PileupRenderer.js.map +1 -1
  99. package/dist/PileupRenderer/colorBy.d.ts +7 -0
  100. package/dist/PileupRenderer/colorBy.js +69 -0
  101. package/dist/PileupRenderer/colorBy.js.map +1 -0
  102. package/dist/PileupRenderer/components/PileupRendering.d.ts +7 -2
  103. package/dist/PileupRenderer/components/PileupRendering.js +17 -18
  104. package/dist/PileupRenderer/components/PileupRendering.js.map +1 -1
  105. package/dist/PileupRenderer/configSchema.d.ts +87 -1
  106. package/dist/PileupRenderer/getAlignmentShapeColor.d.ts +10 -0
  107. package/dist/PileupRenderer/getAlignmentShapeColor.js +60 -0
  108. package/dist/PileupRenderer/getAlignmentShapeColor.js.map +1 -0
  109. package/dist/PileupRenderer/index.js +1 -1
  110. package/dist/PileupRenderer/index.js.map +1 -1
  111. package/dist/PileupRenderer/layoutFeature.d.ts +18 -0
  112. package/dist/PileupRenderer/layoutFeature.js +41 -0
  113. package/dist/PileupRenderer/layoutFeature.js.map +1 -0
  114. package/dist/PileupRenderer/layoutFeatures.d.ts +2 -0
  115. package/dist/PileupRenderer/layoutFeatures.js +35 -0
  116. package/dist/PileupRenderer/layoutFeatures.js.map +1 -0
  117. package/dist/PileupRenderer/makeImageData.d.ts +17 -0
  118. package/dist/PileupRenderer/makeImageData.js +64 -0
  119. package/dist/PileupRenderer/makeImageData.js.map +1 -0
  120. package/dist/PileupRenderer/renderAlignment.d.ts +13 -0
  121. package/dist/PileupRenderer/renderAlignment.js +72 -0
  122. package/dist/PileupRenderer/renderAlignment.js.map +1 -0
  123. package/dist/PileupRenderer/renderAlignmentShape.d.ts +7 -0
  124. package/dist/PileupRenderer/renderAlignmentShape.js +41 -0
  125. package/dist/PileupRenderer/renderAlignmentShape.js.map +1 -0
  126. package/dist/PileupRenderer/renderMethylation.d.ts +11 -0
  127. package/dist/PileupRenderer/renderMethylation.js +63 -0
  128. package/dist/PileupRenderer/renderMethylation.js.map +1 -0
  129. package/dist/PileupRenderer/renderMismatches.d.ts +21 -0
  130. package/dist/PileupRenderer/renderMismatches.js +135 -0
  131. package/dist/PileupRenderer/renderMismatches.js.map +1 -0
  132. package/dist/PileupRenderer/renderModifications.d.ts +11 -0
  133. package/dist/PileupRenderer/renderModifications.js +54 -0
  134. package/dist/PileupRenderer/renderModifications.js.map +1 -0
  135. package/dist/PileupRenderer/renderPerBaseLettering.d.ts +13 -0
  136. package/dist/PileupRenderer/renderPerBaseLettering.js +47 -0
  137. package/dist/PileupRenderer/renderPerBaseLettering.js.map +1 -0
  138. package/dist/PileupRenderer/renderPerBaseQuality.d.ts +9 -0
  139. package/dist/PileupRenderer/renderPerBaseQuality.js +39 -0
  140. package/dist/PileupRenderer/renderPerBaseQuality.js.map +1 -0
  141. package/dist/PileupRenderer/renderSoftClipping.d.ts +13 -0
  142. package/dist/PileupRenderer/renderSoftClipping.js +48 -0
  143. package/dist/PileupRenderer/renderSoftClipping.js.map +1 -0
  144. package/dist/PileupRenderer/sortUtil.js +1 -2
  145. package/dist/PileupRenderer/sortUtil.js.map +1 -1
  146. package/dist/PileupRenderer/util.d.ts +24 -0
  147. package/dist/PileupRenderer/util.js +51 -0
  148. package/dist/PileupRenderer/util.js.map +1 -0
  149. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +1 -3
  150. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +2 -5
  151. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js.map +1 -1
  152. package/dist/SNPCoverageAdapter/configSchema.d.ts +10 -1
  153. package/dist/SNPCoverageAdapter/generateCoverageBins.d.ts +3 -43
  154. package/dist/SNPCoverageAdapter/generateCoverageBins.js +86 -59
  155. package/dist/SNPCoverageAdapter/generateCoverageBins.js.map +1 -1
  156. package/dist/SNPCoverageAdapter/index.js +0 -2
  157. package/dist/SNPCoverageAdapter/index.js.map +1 -1
  158. package/dist/SNPCoverageAdapter/util.d.ts +29 -0
  159. package/dist/SNPCoverageAdapter/util.js +3 -0
  160. package/dist/SNPCoverageAdapter/util.js.map +1 -0
  161. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +1 -1
  162. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -2
  163. package/dist/SNPCoverageRenderer/SNPCoverageRenderer.js.map +1 -1
  164. package/dist/SNPCoverageRenderer/configSchema.d.ts +47 -1
  165. package/dist/SNPCoverageRenderer/configSchema.js +5 -0
  166. package/dist/SNPCoverageRenderer/configSchema.js.map +1 -1
  167. package/dist/shared/BaseDisplayComponent.d.ts +8 -0
  168. package/dist/shared/BaseDisplayComponent.js +49 -0
  169. package/dist/shared/BaseDisplayComponent.js.map +1 -0
  170. package/dist/shared/FilterByTag.d.ts +13 -12
  171. package/dist/shared/FilterByTag.js +8 -13
  172. package/dist/shared/FilterByTag.js.map +1 -1
  173. package/dist/shared/afterAttach.d.ts +2 -0
  174. package/dist/shared/afterAttach.js +44 -0
  175. package/dist/shared/afterAttach.js.map +1 -0
  176. package/dist/shared/color.d.ts +44 -6
  177. package/dist/shared/color.js +57 -23
  178. package/dist/shared/color.js.map +1 -1
  179. package/dist/shared/fetchChains.d.ts +3 -2
  180. package/dist/shared/fetchChains.js +14 -20
  181. package/dist/shared/fetchChains.js.map +1 -1
  182. package/dist/shared/renderSvg.d.ts +7 -0
  183. package/dist/shared/renderSvg.js +69 -0
  184. package/dist/shared/renderSvg.js.map +1 -0
  185. package/dist/shared/util.d.ts +2 -0
  186. package/dist/shared/util.js +13 -0
  187. package/dist/shared/util.js.map +1 -0
  188. package/dist/util.d.ts +16 -2
  189. package/dist/util.js +45 -4
  190. package/dist/util.js.map +1 -1
  191. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureDetail.d.ts +2 -2
  192. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureFlags.d.ts +2 -2
  193. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureFlags.js +3 -2
  194. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureFlags.js.map +1 -1
  195. package/esm/AlignmentsFeatureDetail/AlignmentsFeatureSuppAligns.d.ts +2 -2
  196. package/esm/AlignmentsFeatureDetail/index.d.ts +4 -1
  197. package/esm/AlignmentsTrack/configSchemaF.d.ts +74 -0
  198. package/esm/AlignmentsTrack/configSchemaF.js +16 -0
  199. package/esm/AlignmentsTrack/configSchemaF.js.map +1 -0
  200. package/esm/AlignmentsTrack/index.js +3 -16
  201. package/esm/AlignmentsTrack/index.js.map +1 -1
  202. package/esm/BamAdapter/BamAdapter.d.ts +2 -2
  203. package/esm/BamAdapter/BamAdapter.js +27 -32
  204. package/esm/BamAdapter/BamAdapter.js.map +1 -1
  205. package/esm/BamAdapter/BamSlightlyLazyFeature.d.ts +1 -1
  206. package/esm/BamAdapter/configSchema.d.ts +50 -1
  207. package/esm/CramAdapter/CramAdapter.d.ts +1 -1
  208. package/esm/CramAdapter/CramAdapter.js +50 -48
  209. package/esm/CramAdapter/CramAdapter.js.map +1 -1
  210. package/esm/CramAdapter/CramSlightlyLazyFeature.js +3 -5
  211. package/esm/CramAdapter/CramSlightlyLazyFeature.js.map +1 -1
  212. package/esm/CramAdapter/CramTestAdapters.js +2 -2
  213. package/esm/CramAdapter/CramTestAdapters.js.map +1 -1
  214. package/esm/CramAdapter/configSchema.d.ts +40 -1
  215. package/esm/HtsgetBamAdapter/configSchema.d.ts +26 -1
  216. package/esm/LinearAlignmentsDisplay/components/AlignmentsDisplay.d.ts +2 -2
  217. package/esm/LinearAlignmentsDisplay/models/configSchema.d.ts +39 -1
  218. package/esm/LinearAlignmentsDisplay/models/model.d.ts +20 -6
  219. package/esm/LinearAlignmentsDisplay/models/model.js +9 -4
  220. package/esm/LinearAlignmentsDisplay/models/model.js.map +1 -1
  221. package/esm/LinearPileupDisplay/components/ColorByModifications.d.ts +2 -2
  222. package/esm/LinearPileupDisplay/components/ColorByModifications.js +2 -22
  223. package/esm/LinearPileupDisplay/components/ColorByModifications.js.map +1 -1
  224. package/esm/LinearPileupDisplay/components/ColorByTag.d.ts +2 -2
  225. package/esm/LinearPileupDisplay/components/ColorByTag.js +2 -6
  226. package/esm/LinearPileupDisplay/components/ColorByTag.js.map +1 -1
  227. package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.d.ts +3 -3
  228. package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js +6 -6
  229. package/esm/LinearPileupDisplay/components/LinearPileupDisplayBlurb.js.map +1 -1
  230. package/esm/LinearPileupDisplay/components/ModificationsTable.d.ts +4 -0
  231. package/esm/LinearPileupDisplay/components/ModificationsTable.js +23 -0
  232. package/esm/LinearPileupDisplay/components/ModificationsTable.js.map +1 -0
  233. package/esm/LinearPileupDisplay/components/SetFeatureHeight.d.ts +2 -2
  234. package/esm/LinearPileupDisplay/components/SetMaxHeight.d.ts +2 -2
  235. package/esm/LinearPileupDisplay/components/SetMaxHeight.js +3 -5
  236. package/esm/LinearPileupDisplay/components/SetMaxHeight.js.map +1 -1
  237. package/esm/LinearPileupDisplay/components/SortByTag.d.ts +2 -2
  238. package/esm/LinearPileupDisplay/configSchema.d.ts +57 -1
  239. package/esm/LinearPileupDisplay/model.d.ts +160 -80
  240. package/esm/LinearPileupDisplay/model.js +182 -139
  241. package/esm/LinearPileupDisplay/model.js.map +1 -1
  242. package/esm/LinearReadArcsDisplay/components/ReactComponent.d.ts +2 -2
  243. package/esm/LinearReadArcsDisplay/components/ReactComponent.js +13 -39
  244. package/esm/LinearReadArcsDisplay/components/ReactComponent.js.map +1 -1
  245. package/esm/LinearReadArcsDisplay/configSchema.d.ts +59 -1
  246. package/esm/LinearReadArcsDisplay/drawFeats.d.ts +2 -15
  247. package/esm/LinearReadArcsDisplay/drawFeats.js +56 -63
  248. package/esm/LinearReadArcsDisplay/drawFeats.js.map +1 -1
  249. package/esm/LinearReadArcsDisplay/model.d.ts +58 -193
  250. package/esm/LinearReadArcsDisplay/model.js +69 -119
  251. package/esm/LinearReadArcsDisplay/model.js.map +1 -1
  252. package/esm/LinearReadArcsDisplay/util.d.ts +2 -0
  253. package/esm/LinearReadArcsDisplay/util.js +9 -0
  254. package/esm/LinearReadArcsDisplay/util.js.map +1 -0
  255. package/esm/LinearReadCloudDisplay/components/ReactComponent.d.ts +2 -2
  256. package/esm/LinearReadCloudDisplay/components/ReactComponent.js +11 -36
  257. package/esm/LinearReadCloudDisplay/components/ReactComponent.js.map +1 -1
  258. package/esm/LinearReadCloudDisplay/configSchema.d.ts +52 -1
  259. package/esm/LinearReadCloudDisplay/drawFeats.d.ts +2 -10
  260. package/esm/LinearReadCloudDisplay/drawFeats.js +9 -126
  261. package/esm/LinearReadCloudDisplay/drawFeats.js.map +1 -1
  262. package/esm/LinearReadCloudDisplay/drawLongReadChains.d.ts +11 -0
  263. package/esm/LinearReadCloudDisplay/drawLongReadChains.js +65 -0
  264. package/esm/LinearReadCloudDisplay/drawLongReadChains.js.map +1 -0
  265. package/esm/LinearReadCloudDisplay/drawPairChains.d.ts +17 -0
  266. package/esm/LinearReadCloudDisplay/drawPairChains.js +95 -0
  267. package/esm/LinearReadCloudDisplay/drawPairChains.js.map +1 -0
  268. package/esm/LinearReadCloudDisplay/model.d.ts +65 -196
  269. package/esm/LinearReadCloudDisplay/model.js +59 -96
  270. package/esm/LinearReadCloudDisplay/model.js.map +1 -1
  271. package/esm/LinearReadCloudDisplay/util.d.ts +2 -0
  272. package/esm/LinearReadCloudDisplay/util.js +30 -0
  273. package/esm/LinearReadCloudDisplay/util.js.map +1 -0
  274. package/esm/LinearSNPCoverageDisplay/components/Tooltip.d.ts +2 -2
  275. package/esm/LinearSNPCoverageDisplay/models/configSchema.d.ts +79 -1
  276. package/esm/LinearSNPCoverageDisplay/models/model.d.ts +157 -70
  277. package/esm/LinearSNPCoverageDisplay/models/model.js +48 -35
  278. package/esm/LinearSNPCoverageDisplay/models/model.js.map +1 -1
  279. package/esm/MismatchParser/index.d.ts +7 -2
  280. package/esm/MismatchParser/index.js +41 -4
  281. package/esm/MismatchParser/index.js.map +1 -1
  282. package/esm/PileupRPC/methods/GetReducedFeatures.d.ts +15 -2
  283. package/esm/PileupRPC/methods/GetReducedFeatures.js +2 -9
  284. package/esm/PileupRPC/methods/GetReducedFeatures.js.map +1 -1
  285. package/esm/PileupRenderer/PileupLayoutSession.d.ts +1 -1
  286. package/esm/PileupRenderer/PileupRenderer.d.ts +4 -117
  287. package/esm/PileupRenderer/PileupRenderer.js +20 -754
  288. package/esm/PileupRenderer/PileupRenderer.js.map +1 -1
  289. package/esm/PileupRenderer/colorBy.d.ts +7 -0
  290. package/esm/PileupRenderer/colorBy.js +61 -0
  291. package/esm/PileupRenderer/colorBy.js.map +1 -0
  292. package/esm/PileupRenderer/components/PileupRendering.d.ts +7 -2
  293. package/esm/PileupRenderer/components/PileupRendering.js +17 -18
  294. package/esm/PileupRenderer/components/PileupRendering.js.map +1 -1
  295. package/esm/PileupRenderer/configSchema.d.ts +87 -1
  296. package/esm/PileupRenderer/getAlignmentShapeColor.d.ts +10 -0
  297. package/esm/PileupRenderer/getAlignmentShapeColor.js +56 -0
  298. package/esm/PileupRenderer/getAlignmentShapeColor.js.map +1 -0
  299. package/esm/PileupRenderer/index.js +1 -1
  300. package/esm/PileupRenderer/index.js.map +1 -1
  301. package/esm/PileupRenderer/layoutFeature.d.ts +18 -0
  302. package/esm/PileupRenderer/layoutFeature.js +37 -0
  303. package/esm/PileupRenderer/layoutFeature.js.map +1 -0
  304. package/esm/PileupRenderer/layoutFeatures.d.ts +2 -0
  305. package/esm/PileupRenderer/layoutFeatures.js +31 -0
  306. package/esm/PileupRenderer/layoutFeatures.js.map +1 -0
  307. package/esm/PileupRenderer/makeImageData.d.ts +17 -0
  308. package/esm/PileupRenderer/makeImageData.js +60 -0
  309. package/esm/PileupRenderer/makeImageData.js.map +1 -0
  310. package/esm/PileupRenderer/renderAlignment.d.ts +13 -0
  311. package/esm/PileupRenderer/renderAlignment.js +68 -0
  312. package/esm/PileupRenderer/renderAlignment.js.map +1 -0
  313. package/esm/PileupRenderer/renderAlignmentShape.d.ts +7 -0
  314. package/esm/PileupRenderer/renderAlignmentShape.js +37 -0
  315. package/esm/PileupRenderer/renderAlignmentShape.js.map +1 -0
  316. package/esm/PileupRenderer/renderMethylation.d.ts +11 -0
  317. package/esm/PileupRenderer/renderMethylation.js +59 -0
  318. package/esm/PileupRenderer/renderMethylation.js.map +1 -0
  319. package/esm/PileupRenderer/renderMismatches.d.ts +21 -0
  320. package/esm/PileupRenderer/renderMismatches.js +131 -0
  321. package/esm/PileupRenderer/renderMismatches.js.map +1 -0
  322. package/esm/PileupRenderer/renderModifications.d.ts +11 -0
  323. package/esm/PileupRenderer/renderModifications.js +50 -0
  324. package/esm/PileupRenderer/renderModifications.js.map +1 -0
  325. package/esm/PileupRenderer/renderPerBaseLettering.d.ts +13 -0
  326. package/esm/PileupRenderer/renderPerBaseLettering.js +43 -0
  327. package/esm/PileupRenderer/renderPerBaseLettering.js.map +1 -0
  328. package/esm/PileupRenderer/renderPerBaseQuality.d.ts +9 -0
  329. package/esm/PileupRenderer/renderPerBaseQuality.js +35 -0
  330. package/esm/PileupRenderer/renderPerBaseQuality.js.map +1 -0
  331. package/esm/PileupRenderer/renderSoftClipping.d.ts +13 -0
  332. package/esm/PileupRenderer/renderSoftClipping.js +44 -0
  333. package/esm/PileupRenderer/renderSoftClipping.js.map +1 -0
  334. package/esm/PileupRenderer/sortUtil.js +1 -2
  335. package/esm/PileupRenderer/sortUtil.js.map +1 -1
  336. package/esm/PileupRenderer/util.d.ts +24 -0
  337. package/esm/PileupRenderer/util.js +42 -0
  338. package/esm/PileupRenderer/util.js.map +1 -0
  339. package/esm/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +1 -3
  340. package/esm/SNPCoverageAdapter/SNPCoverageAdapter.js +2 -4
  341. package/esm/SNPCoverageAdapter/SNPCoverageAdapter.js.map +1 -1
  342. package/esm/SNPCoverageAdapter/configSchema.d.ts +10 -1
  343. package/esm/SNPCoverageAdapter/generateCoverageBins.d.ts +3 -43
  344. package/esm/SNPCoverageAdapter/generateCoverageBins.js +87 -60
  345. package/esm/SNPCoverageAdapter/generateCoverageBins.js.map +1 -1
  346. package/esm/SNPCoverageAdapter/index.js +0 -2
  347. package/esm/SNPCoverageAdapter/index.js.map +1 -1
  348. package/esm/SNPCoverageAdapter/util.d.ts +29 -0
  349. package/esm/SNPCoverageAdapter/util.js +2 -0
  350. package/esm/SNPCoverageAdapter/util.js.map +1 -0
  351. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.d.ts +1 -1
  352. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js +2 -2
  353. package/esm/SNPCoverageRenderer/SNPCoverageRenderer.js.map +1 -1
  354. package/esm/SNPCoverageRenderer/configSchema.d.ts +47 -1
  355. package/esm/SNPCoverageRenderer/configSchema.js +5 -0
  356. package/esm/SNPCoverageRenderer/configSchema.js.map +1 -1
  357. package/esm/shared/BaseDisplayComponent.d.ts +8 -0
  358. package/esm/shared/BaseDisplayComponent.js +44 -0
  359. package/esm/shared/BaseDisplayComponent.js.map +1 -0
  360. package/esm/shared/FilterByTag.d.ts +13 -12
  361. package/esm/shared/FilterByTag.js +8 -13
  362. package/esm/shared/FilterByTag.js.map +1 -1
  363. package/esm/shared/afterAttach.d.ts +2 -0
  364. package/esm/shared/afterAttach.js +40 -0
  365. package/esm/shared/afterAttach.js.map +1 -0
  366. package/esm/shared/color.d.ts +44 -6
  367. package/esm/shared/color.js +54 -20
  368. package/esm/shared/color.js.map +1 -1
  369. package/esm/shared/fetchChains.d.ts +3 -2
  370. package/esm/shared/fetchChains.js +14 -20
  371. package/esm/shared/fetchChains.js.map +1 -1
  372. package/esm/shared/renderSvg.d.ts +7 -0
  373. package/esm/shared/renderSvg.js +39 -0
  374. package/esm/shared/renderSvg.js.map +1 -0
  375. package/esm/shared/util.d.ts +2 -0
  376. package/esm/shared/util.js +9 -0
  377. package/esm/shared/util.js.map +1 -0
  378. package/esm/util.d.ts +16 -2
  379. package/esm/util.js +42 -3
  380. package/esm/util.js.map +1 -1
  381. package/package.json +3 -3
  382. package/src/AlignmentsFeatureDetail/AlignmentsFeatureFlags.tsx +3 -5
  383. package/src/AlignmentsFeatureDetail/__snapshots__/index.test.tsx.snap +1 -2
  384. package/src/AlignmentsTrack/configSchemaF.ts +22 -0
  385. package/src/AlignmentsTrack/index.ts +3 -24
  386. package/src/BamAdapter/BamAdapter.ts +46 -44
  387. package/src/CombinationTest.test.ts +2 -2
  388. package/src/CramAdapter/CramAdapter.ts +70 -56
  389. package/src/CramAdapter/CramSlightlyLazyFeature.ts +2 -5
  390. package/src/CramAdapter/CramTestAdapters.ts +2 -2
  391. package/src/LinearAlignmentsDisplay/models/model.tsx +16 -4
  392. package/src/LinearPileupDisplay/components/ColorByModifications.tsx +3 -39
  393. package/src/LinearPileupDisplay/components/ColorByTag.tsx +1 -6
  394. package/src/LinearPileupDisplay/components/LinearPileupDisplayBlurb.tsx +10 -11
  395. package/src/LinearPileupDisplay/components/ModificationsTable.tsx +38 -0
  396. package/src/LinearPileupDisplay/components/SetMaxHeight.tsx +3 -5
  397. package/src/LinearPileupDisplay/model.ts +235 -186
  398. package/src/LinearReadArcsDisplay/components/ReactComponent.tsx +23 -61
  399. package/src/LinearReadArcsDisplay/drawFeats.ts +79 -87
  400. package/src/LinearReadArcsDisplay/model.tsx +77 -155
  401. package/src/LinearReadArcsDisplay/util.ts +10 -0
  402. package/src/LinearReadCloudDisplay/components/ReactComponent.tsx +21 -59
  403. package/src/LinearReadCloudDisplay/drawFeats.ts +12 -166
  404. package/src/LinearReadCloudDisplay/drawLongReadChains.ts +85 -0
  405. package/src/LinearReadCloudDisplay/drawPairChains.ts +139 -0
  406. package/src/LinearReadCloudDisplay/model.tsx +72 -131
  407. package/src/LinearReadCloudDisplay/util.ts +47 -0
  408. package/src/LinearSNPCoverageDisplay/models/model.ts +63 -50
  409. package/src/MismatchParser/index.ts +46 -4
  410. package/src/PileupRPC/methods/GetReducedFeatures.ts +2 -10
  411. package/src/PileupRenderer/PileupLayoutSession.ts +1 -1
  412. package/src/PileupRenderer/PileupRenderer.ts +23 -1190
  413. package/src/PileupRenderer/colorBy.ts +74 -0
  414. package/src/PileupRenderer/components/PileupRendering.tsx +20 -25
  415. package/src/PileupRenderer/getAlignmentShapeColor.ts +87 -0
  416. package/src/PileupRenderer/index.ts +1 -1
  417. package/src/PileupRenderer/layoutFeature.ts +83 -0
  418. package/src/PileupRenderer/layoutFeatures.ts +44 -0
  419. package/src/PileupRenderer/makeImageData.ts +93 -0
  420. package/src/PileupRenderer/renderAlignment.ts +97 -0
  421. package/src/PileupRenderer/renderAlignmentShape.ts +45 -0
  422. package/src/PileupRenderer/renderMethylation.ts +75 -0
  423. package/src/PileupRenderer/renderMismatches.ts +206 -0
  424. package/src/PileupRenderer/renderModifications.ts +74 -0
  425. package/src/PileupRenderer/renderPerBaseLettering.ts +67 -0
  426. package/src/PileupRenderer/renderPerBaseQuality.ts +46 -0
  427. package/src/PileupRenderer/renderSoftClipping.ts +78 -0
  428. package/src/PileupRenderer/sortUtil.ts +1 -3
  429. package/src/PileupRenderer/util.ts +63 -0
  430. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +5 -5
  431. package/src/SNPCoverageAdapter/generateCoverageBins.ts +105 -91
  432. package/src/SNPCoverageAdapter/index.ts +0 -2
  433. package/src/SNPCoverageAdapter/util.ts +33 -0
  434. package/src/SNPCoverageRenderer/SNPCoverageRenderer.ts +3 -3
  435. package/src/SNPCoverageRenderer/configSchema.ts +6 -0
  436. package/src/shared/BaseDisplayComponent.tsx +83 -0
  437. package/src/shared/FilterByTag.tsx +13 -23
  438. package/src/shared/afterAttach.tsx +66 -0
  439. package/src/shared/color.ts +59 -20
  440. package/src/shared/fetchChains.ts +23 -24
  441. package/src/shared/renderSvg.tsx +64 -0
  442. package/src/shared/util.ts +10 -0
  443. package/src/util.ts +54 -5
@@ -1,84 +1,30 @@
1
- import { Theme } from '@mui/material/styles'
2
1
  import BoxRendererType, {
3
2
  RenderArgsDeserialized as BoxRenderArgsDeserialized,
4
3
  } from '@jbrowse/core/pluggableElementTypes/renderers/BoxRendererType'
5
- import { createJBrowseTheme } from '@jbrowse/core/ui'
6
4
  import {
7
- bpSpanPx,
8
- iterMap,
9
- measureText,
10
- Region,
11
5
  Feature,
6
+ Region,
7
+ notEmpty,
8
+ renderToAbstractCanvas,
12
9
  } from '@jbrowse/core/util'
13
- import { renderToAbstractCanvas } from '@jbrowse/core/util/offscreenCanvasUtils'
14
10
  import { BaseLayout } from '@jbrowse/core/util/layouts/BaseLayout'
15
11
  import { getAdapter } from '@jbrowse/core/data_adapters/dataAdapterCache'
16
- import {
17
- readConfObject,
18
- AnyConfigurationModel,
19
- } from '@jbrowse/core/configuration'
20
-
21
- // locals
22
- import {
23
- Mismatch,
24
- parseCigar,
25
- getModificationPositions,
26
- getNextRefPos,
27
- } from '../MismatchParser'
28
- import { sortFeature } from './sortUtil'
29
- import {
30
- getTagAlt,
31
- orientationTypes,
32
- fetchSequence,
33
- shouldFetchReferenceSequence,
34
- } from '../util'
35
12
  import {
36
13
  PileupLayoutSession,
37
14
  PileupLayoutSessionProps,
38
15
  } from './PileupLayoutSession'
39
16
  import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
40
17
 
41
- function fillRect(
42
- ctx: CanvasRenderingContext2D,
43
- l: number,
44
- t: number,
45
- w: number,
46
- h: number,
47
- cw: number,
48
- color?: string,
49
- ) {
50
- if (l + w < 0 || l > cw) {
51
- return
52
- } else {
53
- if (color) {
54
- ctx.fillStyle = color
55
- }
56
- ctx.fillRect(l, t, w, h)
57
- }
58
- }
59
-
60
- function getColorBaseMap(theme: Theme) {
61
- const { bases } = theme.palette
62
- return {
63
- A: bases.A.main,
64
- C: bases.C.main,
65
- G: bases.G.main,
66
- T: bases.T.main,
67
- deletion: '#808080', // gray
68
- }
69
- }
70
-
71
- function getContrastBaseMap(theme: Theme) {
72
- const map = getColorBaseMap(theme)
73
- return Object.fromEntries(
74
- Object.entries(map).map(([k, v]) => [k, theme.palette.getContrastText(v)]),
75
- )
76
- }
18
+ // locals
19
+ import { fetchSequence, shouldFetchReferenceSequence } from '../util'
20
+ import { layoutFeats } from './layoutFeatures'
21
+ import { makeImageData } from './makeImageData'
22
+ import { readConfObject } from '@jbrowse/core/configuration'
77
23
 
78
24
  export interface RenderArgsDeserialized extends BoxRenderArgsDeserialized {
79
25
  colorBy?: { type: string; tag?: string }
80
26
  colorTagMap?: Record<string, string>
81
- modificationTagMap?: Record<string, string>
27
+ modificationTagMap?: Record<string, string | undefined>
82
28
  sortedBy?: {
83
29
  type: string
84
30
  pos: number
@@ -97,130 +43,25 @@ export interface RenderArgsDeserializedWithFeaturesAndLayout
97
43
  regionSequence?: string
98
44
  }
99
45
 
100
- interface LayoutRecord {
101
- feature: Feature
102
- leftPx: number
103
- rightPx: number
104
- topPx: number
105
- heightPx: number
106
- }
107
-
108
- const alignmentColoring: { [key: string]: string } = {
109
- color_fwd_strand_not_proper: '#ECC8C8',
110
- color_rev_strand_not_proper: '#BEBED8',
111
- color_fwd_strand: '#EC8B8B',
112
- color_rev_strand: '#8F8FD8',
113
- color_fwd_missing_mate: '#D11919',
114
- color_rev_missing_mate: '#1919D1',
115
- color_fwd_diff_chr: '#000',
116
- color_rev_diff_chr: '#969696',
117
- color_pair_lr: '#c8c8c8',
118
- color_pair_rr: 'navy',
119
- color_pair_rl: 'teal',
120
- color_pair_ll: 'green',
121
- color_nostrand: '#c8c8c8',
122
- color_interchrom: 'orange',
123
- color_longinsert: 'red',
124
- color_shortinsert: 'pink',
125
- }
126
-
127
- interface LayoutFeature {
128
- heightPx: number
129
- topPx: number
130
- feature: Feature
131
- }
132
-
133
- function shouldDrawSNPsMuted(type?: string) {
134
- return ['methylation', 'modifications'].includes(type || '')
135
- }
136
-
137
- function shouldDrawIndels(type?: string) {
138
- return true
139
- }
140
-
141
46
  export default class PileupRenderer extends BoxRendererType {
142
47
  supportsSVG = true
143
48
 
144
- // get width and height of chars the height is an approximation: width
145
- // letter M is approximately the height
146
- getCharWidthHeight() {
147
- const charWidth = measureText('A')
148
- const charHeight = measureText('M') - 2
149
- return { charWidth, charHeight }
150
- }
151
-
152
- layoutFeature({
153
- feature,
154
- layout,
155
- bpPerPx,
156
- region,
157
- showSoftClip,
158
- heightPx,
159
- displayMode,
160
- }: {
161
- feature: Feature
162
- layout: BaseLayout<Feature>
163
- bpPerPx: number
164
- region: Region
165
- showSoftClip?: boolean
166
- heightPx: number
167
- displayMode: string
168
- }): LayoutRecord | null {
169
- let expansionBefore = 0
170
- let expansionAfter = 0
171
-
172
- // Expand the start and end of feature when softclipping enabled
173
- if (showSoftClip) {
174
- const mismatches = feature.get('mismatches') as Mismatch[] | undefined
175
- const seq = feature.get('seq') as string
176
- if (seq && mismatches) {
177
- for (let i = 0; i < mismatches.length; i += 1) {
178
- const { type, start, cliplen = 0 } = mismatches[i]
179
- if (type === 'softclip') {
180
- start === 0
181
- ? (expansionBefore = cliplen)
182
- : (expansionAfter = cliplen)
183
- }
184
- }
185
- }
186
- }
187
- const s = feature.get('start') - expansionBefore
188
- const e = feature.get('end') + expansionAfter
189
-
190
- const [leftPx, rightPx] = bpSpanPx(s, e, region, bpPerPx)
191
-
192
- if (displayMode === 'compact') {
193
- heightPx /= 3
194
- }
195
- if (feature.get('refName') !== region.refName) {
196
- throw new Error(
197
- `feature ${feature.id()} is not on the current region's reference sequence ${
198
- region.refName
199
- }`,
200
- )
201
- }
202
- const topPx = layout.addRect(feature.id(), s, e, heightPx, feature)
203
- if (topPx === null) {
204
- return null
205
- }
206
-
207
- return {
208
- feature,
209
- leftPx,
210
- rightPx,
211
- topPx: displayMode === 'collapse' ? 0 : topPx,
212
- heightPx,
49
+ async fetchSequence(renderProps: RenderArgsDeserialized) {
50
+ const { sessionId, regions, adapterConfig } = renderProps
51
+ const { sequenceAdapter } = adapterConfig
52
+ if (!sequenceAdapter) {
53
+ return undefined
213
54
  }
55
+ const pm = this.pluginManager
56
+ const { dataAdapter } = await getAdapter(pm, sessionId, sequenceAdapter)
57
+ const [region] = regions
58
+ return fetchSequence(region, dataAdapter as BaseFeatureDataAdapter)
214
59
  }
215
60
 
216
- // expands region for clipping to use. possible improvement: use average read
217
- // size to set the heuristic maxClippingSize expansion (e.g. short reads
218
- // don't have to expand a softclipping size a lot, but long reads might)
219
61
  getExpandedRegion(region: Region, renderArgs: RenderArgsDeserialized) {
220
62
  const { config, showSoftClip } = renderArgs
221
-
222
- const maxClippingSize = readConfObject(config, 'maxClippingSize')
223
63
  const { start, end } = region
64
+ const maxClippingSize = readConfObject(config, 'maxClippingSize')
224
65
  const bpExpansion = showSoftClip ? Math.round(maxClippingSize) : 0
225
66
 
226
67
  return {
@@ -231,1019 +72,13 @@ export default class PileupRenderer extends BoxRendererType {
231
72
  }
232
73
  }
233
74
 
234
- colorByOrientation(feature: Feature, config: AnyConfigurationModel) {
235
- return alignmentColoring[
236
- this.getOrientation(feature, config) || 'color_nostrand'
237
- ]
238
- }
239
-
240
- getOrientation(feature: Feature, config: AnyConfigurationModel) {
241
- const orientationType = readConfObject(config, 'orientationType') as
242
- | 'fr'
243
- | 'ff'
244
- | 'rf'
245
- const type = orientationTypes[orientationType]
246
- const orientation = type[feature.get('pair_orientation') as string]
247
- const map: { [key: string]: string } = {
248
- LR: 'color_pair_lr',
249
- RR: 'color_pair_rr',
250
- RL: 'color_pair_rl',
251
- LL: 'color_pair_ll',
252
- }
253
- return map[orientation]
254
- }
255
-
256
- colorByInsertSize(feature: Feature, _config: AnyConfigurationModel) {
257
- return feature.get('is_paired') &&
258
- feature.get('refName') !== feature.get('next_ref')
259
- ? '#555'
260
- : `hsl(${Math.abs(feature.get('template_length')) / 10},50%,50%)`
261
- }
262
-
263
- colorByStranded(feature: Feature, _config: AnyConfigurationModel) {
264
- const flags = feature.get('flags')
265
- const strand = feature.get('strand')
266
- // is paired
267
- if (flags & 1) {
268
- const revflag = flags & 64
269
- const flipper = revflag ? -1 : 1
270
- // proper pairing
271
- if (flags & 2) {
272
- return strand * flipper === 1 ? 'color_rev_strand' : 'color_fwd_strand'
273
- }
274
- if (feature.get('multi_segment_next_segment_unmapped')) {
275
- return strand * flipper === 1
276
- ? 'color_rev_missing_mate'
277
- : 'color_fwd_missing_mate'
278
- }
279
- if (feature.get('refName') === feature.get('next_refName')) {
280
- return strand * flipper === 1
281
- ? 'color_rev_strand_not_proper'
282
- : 'color_fwd_strand_not_proper'
283
- }
284
- // should only leave aberrant chr
285
- return strand === 1 ? 'color_fwd_diff_chr' : 'color_rev_diff_chr'
286
- }
287
- return strand === 1 ? 'color_fwd_strand' : 'color_rev_strand'
288
- }
289
-
290
- colorByPerBaseLettering({
291
- ctx,
292
- feat,
293
- region,
294
- bpPerPx,
295
- colorForBase,
296
- contrastForBase,
297
- charWidth,
298
- charHeight,
299
- canvasWidth,
300
- }: {
301
- ctx: CanvasRenderingContext2D
302
- feat: LayoutFeature
303
- region: Region
304
- bpPerPx: number
305
- colorForBase: Record<string, string>
306
- contrastForBase: Record<string, string>
307
- charWidth: number
308
- charHeight: number
309
- canvasWidth: number
310
- }) {
311
- const heightLim = charHeight - 2
312
- const { feature, topPx, heightPx } = feat
313
- const seq = feature.get('seq') as string
314
- const cigarOps = parseCigar(feature.get('CIGAR'))
315
- const w = 1 / bpPerPx
316
- const start = feature.get('start')
317
- let soffset = 0 // sequence offset
318
- let roffset = 0 // reference offset
319
-
320
- for (let i = 0; i < cigarOps.length; i += 2) {
321
- const len = +cigarOps[i]
322
- const op = cigarOps[i + 1]
323
- if (op === 'S' || op === 'I') {
324
- soffset += len
325
- } else if (op === 'D' || op === 'N') {
326
- roffset += len
327
- } else if (op === 'M' || op === 'X' || op === '=') {
328
- for (let m = 0; m < len; m++) {
329
- const letter = seq[soffset + m]
330
- const r = start + roffset + m
331
- const [leftPx] = bpSpanPx(r, r + 1, region, bpPerPx)
332
- fillRect(
333
- ctx,
334
- leftPx,
335
- topPx,
336
- w + 0.5,
337
- heightPx,
338
- canvasWidth,
339
- colorForBase[letter],
340
- )
341
-
342
- if (w >= charWidth && heightPx >= heightLim) {
343
- // normal SNP coloring
344
- ctx.fillStyle = contrastForBase[letter]
345
-
346
- ctx.fillText(
347
- letter,
348
- leftPx + (w - charWidth) / 2 + 1,
349
- topPx + heightPx,
350
- )
351
- }
352
- }
353
- soffset += len
354
- roffset += len
355
- }
356
- }
357
- }
358
- colorByPerBaseQuality({
359
- ctx,
360
- feat,
361
- region,
362
- bpPerPx,
363
- canvasWidth,
364
- }: {
365
- ctx: CanvasRenderingContext2D
366
- feat: LayoutFeature
367
- region: Region
368
- bpPerPx: number
369
- canvasWidth: number
370
- }) {
371
- const { feature, topPx, heightPx } = feat
372
- const qual: string = feature.get('qual') || ''
373
- const scores = qual.split(' ').map(val => +val)
374
- const cigarOps = parseCigar(feature.get('CIGAR'))
375
- const width = 1 / bpPerPx
376
- const start = feature.get('start')
377
- let soffset = 0 // sequence offset
378
- let roffset = 0 // reference offset
379
-
380
- for (let i = 0; i < cigarOps.length; i += 2) {
381
- const len = +cigarOps[i]
382
- const op = cigarOps[i + 1]
383
- if (op === 'S' || op === 'I') {
384
- soffset += len
385
- } else if (op === 'D' || op === 'N') {
386
- roffset += len
387
- } else if (op === 'M' || op === 'X' || op === '=') {
388
- for (let m = 0; m < len; m++) {
389
- const score = scores[soffset + m]
390
- const [leftPx] = bpSpanPx(
391
- start + roffset + m,
392
- start + roffset + m + 1,
393
- region,
394
- bpPerPx,
395
- )
396
- fillRect(
397
- ctx,
398
- leftPx,
399
- topPx,
400
- width + 0.5,
401
- heightPx,
402
- canvasWidth,
403
- `hsl(${score === 255 ? 150 : score * 1.5},55%,50%)`,
404
- )
405
- }
406
- soffset += len
407
- roffset += len
408
- }
409
- }
410
- }
411
-
412
- // ML stores probabilities as array of numerics and MP is scaled phred scores
413
- // https://github.com/samtools/hts-specs/pull/418/files#diff-e765c6479316309f56b636f88189cdde8c40b854c7bdcce9ee7fe87a4e76febcR596
414
- //
415
- // if we have ML or Ml, it is an 8bit probability, divide by 255
416
- //
417
- // if we have MP or Mp it is phred scaled ASCII, which can go up to 90 but
418
- // has very high likelihood basecalls at that point, we really only care
419
- // about low qual calls <20 approx
420
- //
421
- colorByModifications({
422
- ctx,
423
- feat,
424
- region,
425
- bpPerPx,
426
- renderArgs,
427
- canvasWidth,
428
- }: {
429
- ctx: CanvasRenderingContext2D
430
- feat: LayoutFeature
431
- region: Region
432
- bpPerPx: number
433
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
434
- canvasWidth: number
435
- }) {
436
- const { feature, topPx, heightPx } = feat
437
- const { Color, modificationTagMap = {} } = renderArgs
438
-
439
- const mm = (getTagAlt(feature, 'MM', 'Mm') as string) || ''
440
-
441
- const ml = (getTagAlt(feature, 'ML', 'Ml') as number[] | string) || []
442
-
443
- const probabilities = ml
444
- ? (typeof ml === 'string' ? ml.split(',').map(e => +e) : ml).map(
445
- e => e / 255,
446
- )
447
- : (getTagAlt(feature, 'MP', 'Mp') as string)
448
- .split('')
449
- .map(s => s.charCodeAt(0) - 33)
450
- .map(elt => Math.min(1, elt / 50))
451
-
452
- const cigar = feature.get('CIGAR')
453
- const start = feature.get('start')
454
- const seq = feature.get('seq')
455
- const strand = feature.get('strand')
456
- const cigarOps = parseCigar(cigar)
457
-
458
- const modifications = getModificationPositions(mm, seq, strand)
459
-
460
- // probIndex applies across multiple modifications e.g.
461
- let probIndex = 0
462
- for (const { type, positions } of modifications) {
463
- const col = modificationTagMap[type] || 'black'
464
-
465
- // @ts-expect-error
466
- const base = Color(col)
467
- for (const readPos of getNextRefPos(cigarOps, positions)) {
468
- const r = start + readPos
469
- const [leftPx, rightPx] = bpSpanPx(r, r + 1, region, bpPerPx)
470
-
471
- // give it a little boost of 0.1 to not make them fully
472
- // invisible to avoid confusion
473
- const prob = probabilities[probIndex]
474
-
475
- fillRect(
476
- ctx,
477
- leftPx,
478
- topPx,
479
- rightPx - leftPx + 0.5,
480
- heightPx,
481
- canvasWidth,
482
- prob && prob !== 1
483
- ? base
484
- .alpha(prob + 0.1)
485
- .hsl()
486
- .string()
487
- : col,
488
- )
489
- probIndex++
490
- }
491
- }
492
- }
493
-
494
- // Color by methylation is slightly modified version of color by
495
- // modifications that focuses on CpG sites, with non-methylated CpG colored
496
- // blue
497
- colorByMethylation({
498
- ctx,
499
- feat,
500
- region,
501
- bpPerPx,
502
- renderArgs,
503
- canvasWidth,
504
- }: {
505
- ctx: CanvasRenderingContext2D
506
- feat: LayoutFeature
507
- region: Region
508
- bpPerPx: number
509
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
510
- canvasWidth: number
511
- }) {
512
- const { regionSequence } = renderArgs
513
- const { feature, topPx, heightPx } = feat
514
-
515
- const mm: string = getTagAlt(feature, 'MM', 'Mm') || ''
516
-
517
- if (!regionSequence) {
518
- throw new Error('region sequence required for methylation')
519
- }
520
-
521
- const cigar = feature.get('CIGAR')
522
- const fstart = feature.get('start')
523
- const fend = feature.get('end')
524
- const seq = feature.get('seq')
525
- const strand = feature.get('strand')
526
- const cigarOps = parseCigar(cigar)
527
-
528
- const methBins = new Array(region.end - region.start).fill(0)
529
- const modifications = getModificationPositions(mm, seq, strand)
530
- for (let i = 0; i < modifications.length; i++) {
531
- const { type, positions } = modifications[i]
532
- if (type === 'm' && positions) {
533
- for (const pos of getNextRefPos(cigarOps, positions)) {
534
- const epos = pos + fstart - region.start
535
- if (epos >= 0 && epos < methBins.length) {
536
- methBins[epos] = 1
537
- }
538
- }
539
- }
540
- }
541
-
542
- for (let j = fstart; j < fend; j++) {
543
- const i = j - region.start
544
- if (i >= 0 && i < methBins.length) {
545
- const l1 = regionSequence[i].toLowerCase()
546
- const l2 = regionSequence[i + 1].toLowerCase()
547
-
548
- // if we are zoomed out, display just a block over the cpg
549
- if (bpPerPx > 2) {
550
- if (l1 === 'c' && l2 === 'g') {
551
- const s = region.start + i
552
- const [leftPx, rightPx] = bpSpanPx(s, s + 2, region, bpPerPx)
553
- fillRect(
554
- ctx,
555
- leftPx,
556
- topPx,
557
- rightPx - leftPx + 0.5,
558
- heightPx,
559
- canvasWidth,
560
- methBins[i] || methBins[i + 1] ? 'red' : 'blue',
561
- )
562
- }
563
- }
564
- // if we are zoomed in, color the c inside the cpg
565
- else {
566
- // color
567
- if (l1 === 'c' && l2 === 'g') {
568
- const s = region.start + i
569
- const [leftPx, rightPx] = bpSpanPx(s, s + 1, region, bpPerPx)
570
- fillRect(
571
- ctx,
572
- leftPx,
573
- topPx,
574
- rightPx - leftPx + 0.5,
575
- heightPx,
576
- canvasWidth,
577
- methBins[i] ? 'red' : 'blue',
578
- )
579
-
580
- const [leftPx2, rightPx2] = bpSpanPx(s + 1, s + 2, region, bpPerPx)
581
- fillRect(
582
- ctx,
583
- leftPx2,
584
- topPx,
585
- rightPx2 - leftPx2 + 0.5,
586
- heightPx,
587
- canvasWidth,
588
- methBins[i + 1] ? 'red' : 'blue',
589
- )
590
- }
591
- }
592
- }
593
- }
594
- }
595
-
596
- drawRect(
597
- ctx: CanvasRenderingContext2D,
598
- feat: LayoutFeature,
599
- props: RenderArgsDeserialized,
600
- ) {
601
- const { regions, bpPerPx } = props
602
- const { heightPx, topPx, feature } = feat
603
- const [region] = regions
604
- const [leftPx, rightPx] = bpSpanPx(
605
- feature.get('start'),
606
- feature.get('end'),
607
- region,
608
- bpPerPx,
609
- )
610
- const flip = region.reversed ? -1 : 1
611
- const strand = feature.get('strand') * flip
612
- if (bpPerPx < 10) {
613
- if (strand === -1) {
614
- ctx.beginPath()
615
- ctx.moveTo(leftPx - 5, topPx + heightPx / 2)
616
- ctx.lineTo(leftPx, topPx + heightPx)
617
- ctx.lineTo(rightPx, topPx + heightPx)
618
- ctx.lineTo(rightPx, topPx)
619
- ctx.lineTo(leftPx, topPx)
620
- ctx.closePath()
621
- ctx.fill()
622
- } else {
623
- ctx.beginPath()
624
- ctx.moveTo(leftPx, topPx)
625
- ctx.lineTo(leftPx, topPx + heightPx)
626
- ctx.lineTo(rightPx, topPx + heightPx)
627
- ctx.lineTo(rightPx + 5, topPx + heightPx / 2)
628
- ctx.lineTo(rightPx, topPx)
629
- ctx.closePath()
630
- ctx.fill()
631
- }
632
- } else {
633
- ctx.fillRect(leftPx, topPx, rightPx - leftPx, heightPx)
634
- }
635
- }
636
-
637
- drawAlignmentRect({
638
- ctx,
639
- feat,
640
- renderArgs,
641
- colorForBase,
642
- contrastForBase,
643
- charWidth,
644
- charHeight,
645
- defaultColor,
646
- theme,
647
- canvasWidth,
648
- }: {
649
- ctx: CanvasRenderingContext2D
650
- feat: LayoutFeature
651
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
652
- colorForBase: Record<string, string>
653
- contrastForBase: Record<string, string>
654
- charWidth: number
655
- charHeight: number
656
- defaultColor: boolean
657
- canvasWidth: number
658
- theme: Theme
659
- }) {
660
- const { config, bpPerPx, regions, colorBy, colorTagMap = {} } = renderArgs
661
- const { tag = '', type: colorType = '' } = colorBy || {}
662
- const { feature } = feat
663
- const region = regions[0]
664
-
665
- // first pass for simple color changes that change the color of the
666
- // alignment
667
- switch (colorType) {
668
- case 'insertSize':
669
- ctx.fillStyle = this.colorByInsertSize(feature, config)
670
- break
671
- case 'strand':
672
- ctx.fillStyle = feature.get('strand') === -1 ? '#8F8FD8' : '#EC8B8B'
673
- break
674
- case 'mappingQuality':
675
- ctx.fillStyle = `hsl(${feature.get('mq')},50%,50%)`
676
- break
677
-
678
- case 'pairOrientation':
679
- ctx.fillStyle = this.colorByOrientation(feature, config)
680
- break
681
- case 'stranded':
682
- ctx.fillStyle = alignmentColoring[this.colorByStranded(feature, config)]
683
- break
684
- case 'xs':
685
- case 'tag': {
686
- const tags = feature.get('tags')
687
- const val = tags ? tags[tag] : feature.get(tag)
688
-
689
- // special for for XS/TS tag
690
- if (tag === 'XS' || tag === 'TS') {
691
- const map: { [key: string]: string | undefined } = {
692
- '-': 'color_rev_strand',
693
- '+': 'color_fwd_strand',
694
- }
695
- ctx.fillStyle = alignmentColoring[map[val] || 'color_nostrand']
696
- }
697
-
698
- // lower case 'ts' from minimap2 is flipped from xs
699
- if (tag === 'ts') {
700
- const map: { [key: string]: string } = {
701
- '-':
702
- feature.get('strand') === -1
703
- ? 'color_fwd_strand'
704
- : 'color_rev_strand',
705
- '+':
706
- feature.get('strand') === -1
707
- ? 'color_rev_strand'
708
- : 'color_fwd_strand',
709
- }
710
- ctx.fillStyle = alignmentColoring[map[val] || 'color_nostrand']
711
- }
712
-
713
- // tag is not one of the autofilled tags, has color-value pairs from
714
- // fetchValues
715
- else {
716
- const foundValue = colorTagMap[val]
717
- ctx.fillStyle = foundValue || alignmentColoring['color_nostrand']
718
- }
719
- break
720
- }
721
- case 'insertSizeAndPairOrientation': {
722
- break
723
- }
724
-
725
- case 'modifications':
726
- case 'methylation': {
727
- // this coloring is similar to igv.js, and is helpful to color negative
728
- // strand reads differently because their c-g will be flipped (e.g. g-c
729
- // read right to left)
730
- ctx.fillStyle = feature.get('flags') & 16 ? '#c8dcc8' : '#c8c8c8'
731
- break
732
- }
733
-
734
- default: {
735
- ctx.fillStyle = defaultColor
736
- ? 'lightgrey'
737
- : readConfObject(config, 'color', { feature })
738
- break
739
- }
740
- }
741
-
742
- this.drawRect(ctx, feat, renderArgs)
743
-
744
- // second pass for color types that render per-base things that go over the
745
- // existing drawing
746
- switch (colorType) {
747
- case 'perBaseQuality':
748
- this.colorByPerBaseQuality({
749
- ctx,
750
- feat,
751
- region,
752
- bpPerPx,
753
- canvasWidth,
754
- })
755
- break
756
-
757
- case 'perBaseLettering':
758
- this.colorByPerBaseLettering({
759
- ctx,
760
- feat,
761
- region,
762
- bpPerPx,
763
- colorForBase,
764
- contrastForBase,
765
- charWidth,
766
- charHeight,
767
- canvasWidth,
768
- })
769
- break
770
-
771
- case 'modifications':
772
- this.colorByModifications({
773
- ctx,
774
- feat,
775
- region,
776
- bpPerPx,
777
- renderArgs,
778
- canvasWidth,
779
- })
780
- break
781
-
782
- case 'methylation':
783
- this.colorByMethylation({
784
- ctx,
785
- feat,
786
- region,
787
- bpPerPx,
788
- renderArgs,
789
- canvasWidth,
790
- })
791
- break
792
- }
793
- }
794
-
795
- drawMismatches({
796
- ctx,
797
- feat,
798
- renderArgs,
799
- minSubfeatureWidth,
800
- largeInsertionIndicatorScale,
801
- mismatchAlpha,
802
- charWidth,
803
- charHeight,
804
- colorForBase,
805
- contrastForBase,
806
- canvasWidth,
807
- drawSNPsMuted,
808
- drawIndels = true,
809
- }: {
810
- ctx: CanvasRenderingContext2D
811
- feat: LayoutFeature
812
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
813
- colorForBase: { [key: string]: string }
814
- contrastForBase: { [key: string]: string }
815
- mismatchAlpha?: boolean
816
- drawIndels?: boolean
817
- drawSNPsMuted?: boolean
818
- minSubfeatureWidth: number
819
- largeInsertionIndicatorScale: number
820
- charWidth: number
821
- charHeight: number
822
- canvasWidth: number
823
- theme: Theme
824
- }) {
825
- const { Color, bpPerPx, regions } = renderArgs
826
- const { heightPx, topPx, feature } = feat
827
- const [region] = regions
828
- const start = feature.get('start')
829
-
830
- const pxPerBp = Math.min(1 / bpPerPx, 2)
831
- const w = Math.max(minSubfeatureWidth, pxPerBp)
832
- const mismatches = feature.get('mismatches') as Mismatch[] | undefined
833
- const heightLim = charHeight - 2
834
-
835
- // extraHorizontallyFlippedOffset is used to draw interbase items, which
836
- // are located to the left when forward and right when reversed
837
- const extraHorizontallyFlippedOffset = region.reversed
838
- ? 1 / bpPerPx + 1
839
- : -1
840
-
841
- if (!mismatches) {
842
- return
843
- }
844
-
845
- // two pass rendering: first pass, draw all the mismatches except wide
846
- // insertion markers
847
- for (let i = 0; i < mismatches.length; i += 1) {
848
- const mismatch = mismatches[i]
849
- const mstart = start + mismatch.start
850
- const mlen = mismatch.length
851
- const mbase = mismatch.base
852
- const [leftPx, rightPx] = bpSpanPx(mstart, mstart + mlen, region, bpPerPx)
853
- const widthPx = Math.max(minSubfeatureWidth, Math.abs(leftPx - rightPx))
854
- if (mismatch.type === 'mismatch') {
855
- if (!drawSNPsMuted) {
856
- const baseColor = colorForBase[mismatch.base] || '#888'
857
-
858
- fillRect(
859
- ctx,
860
- Math.round(leftPx),
861
- topPx,
862
- widthPx,
863
- heightPx,
864
- canvasWidth,
865
-
866
- mismatchAlpha
867
- ? mismatch.qual === undefined
868
- ? baseColor
869
- : // @ts-expect-error
870
- Color(baseColor)
871
- .alpha(Math.min(1, mismatch.qual / 50))
872
- .hsl()
873
- .string()
874
- : baseColor,
875
- )
876
- }
877
-
878
- if (widthPx >= charWidth && heightPx >= heightLim) {
879
- // normal SNP coloring
880
- const contrastColor = drawSNPsMuted
881
- ? 'black'
882
- : contrastForBase[mismatch.base] || 'black'
883
- ctx.fillStyle = mismatchAlpha
884
- ? mismatch.qual === undefined
885
- ? contrastColor
886
- : // @ts-expect-error
887
- Color(contrastColor)
888
- .alpha(Math.min(1, mismatch.qual / 50))
889
- .hsl()
890
- .string()
891
- : contrastColor
892
- ctx.fillText(
893
- mbase,
894
- leftPx + (widthPx - charWidth) / 2 + 1,
895
- topPx + heightPx,
896
- )
897
- }
898
- } else if (mismatch.type === 'deletion' && drawIndels) {
899
- fillRect(
900
- ctx,
901
- leftPx,
902
- topPx,
903
- Math.abs(leftPx - rightPx),
904
- heightPx,
905
- canvasWidth,
906
- colorForBase.deletion,
907
- )
908
- const txt = `${mismatch.length}`
909
- const rwidth = measureText(txt, 10)
910
- if (widthPx >= rwidth && heightPx >= heightLim) {
911
- ctx.fillStyle = contrastForBase.deletion
912
- ctx.fillText(
913
- txt,
914
- (leftPx + rightPx) / 2 - rwidth / 2,
915
- topPx + heightPx,
916
- )
917
- }
918
- } else if (mismatch.type === 'insertion' && drawIndels) {
919
- ctx.fillStyle = 'purple'
920
- const pos = leftPx + extraHorizontallyFlippedOffset
921
- const len = +mismatch.base || mismatch.length
922
- const insW = Math.max(0, Math.min(1.2, 1 / bpPerPx))
923
- if (len < 10) {
924
- fillRect(ctx, pos, topPx, insW, heightPx, canvasWidth, 'purple')
925
- if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
926
- fillRect(ctx, pos - insW, topPx, insW * 3, 1, canvasWidth)
927
- fillRect(
928
- ctx,
929
- pos - insW,
930
- topPx + heightPx - 1,
931
- insW * 3,
932
- 1,
933
- canvasWidth,
934
- )
935
- ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
936
- }
937
- }
938
- } else if (mismatch.type === 'hardclip' || mismatch.type === 'softclip') {
939
- const pos = leftPx + extraHorizontallyFlippedOffset
940
- fillRect(
941
- ctx,
942
- pos,
943
- topPx,
944
- w,
945
- heightPx,
946
- canvasWidth,
947
- mismatch.type === 'hardclip' ? 'red' : 'blue',
948
- )
949
- if (1 / bpPerPx >= charWidth && heightPx >= heightLim) {
950
- fillRect(ctx, pos - w, topPx, w * 3, 1, canvasWidth)
951
- fillRect(ctx, pos - w, topPx + heightPx - 1, w * 3, 1, canvasWidth)
952
- ctx.fillText(`(${mismatch.base})`, pos + 3, topPx + heightPx)
953
- }
954
- } else if (mismatch.type === 'skip') {
955
- // fix to avoid bad rendering note that this was also related to chrome
956
- // bug https://bugs.chromium.org/p/chromium/issues/detail?id=1131528
957
- // also affected firefox ref #1236 #2750
958
- if (leftPx + widthPx > 0) {
959
- // make small exons more visible when zoomed far out
960
- const adjustPx = widthPx - (bpPerPx > 10 ? 1.5 : 0)
961
- ctx.clearRect(leftPx, topPx, adjustPx, heightPx)
962
- fillRect(
963
- ctx,
964
- Math.max(0, leftPx),
965
- topPx + heightPx / 2 - 1,
966
- adjustPx + (leftPx < 0 ? leftPx : 0),
967
- 2,
968
- canvasWidth,
969
- '#333',
970
- )
971
- }
972
- }
973
- }
974
-
975
- // second pass, draw wide insertion markers on top
976
- if (drawIndels) {
977
- for (let i = 0; i < mismatches.length; i += 1) {
978
- const mismatch = mismatches[i]
979
- const mstart = start + mismatch.start
980
- const mlen = mismatch.length
981
- const [leftPx] = bpSpanPx(mstart, mstart + mlen, region, bpPerPx)
982
- const len = +mismatch.base || mismatch.length
983
- const txt = `${len}`
984
- if (mismatch.type === 'insertion' && len >= 10) {
985
- if (bpPerPx > largeInsertionIndicatorScale) {
986
- fillRect(ctx, leftPx - 1, topPx, 2, heightPx, canvasWidth, 'purple')
987
- } else if (heightPx > charHeight) {
988
- const rwidth = measureText(txt)
989
- const padding = 5
990
- fillRect(
991
- ctx,
992
- leftPx - rwidth / 2 - padding,
993
- topPx,
994
- rwidth + 2 * padding,
995
- heightPx,
996
- canvasWidth,
997
- 'purple',
998
- )
999
- ctx.fillStyle = 'white'
1000
- ctx.fillText(txt, leftPx - rwidth / 2, topPx + heightPx)
1001
- } else {
1002
- const padding = 2
1003
- fillRect(
1004
- ctx,
1005
- leftPx - padding,
1006
- topPx,
1007
- 2 * padding,
1008
- heightPx,
1009
- canvasWidth,
1010
- 'purple',
1011
- )
1012
- }
1013
- }
1014
- }
1015
- }
1016
- }
1017
-
1018
- drawSoftClipping({
1019
- ctx,
1020
- feat,
1021
- renderArgs,
1022
- config,
1023
- theme,
1024
- canvasWidth,
1025
- }: {
1026
- ctx: CanvasRenderingContext2D
1027
- feat: LayoutFeature
1028
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
1029
- config: AnyConfigurationModel
1030
- theme: Theme
1031
- canvasWidth: number
1032
- }) {
1033
- const { feature, topPx, heightPx } = feat
1034
- const { regions, bpPerPx } = renderArgs
1035
- const [region] = regions
1036
- const minFeatWidth = readConfObject(config, 'minSubfeatureWidth')
1037
- const mismatches = feature.get('mismatches') as Mismatch[] | undefined
1038
- const seq = feature.get('seq')
1039
- const { charWidth, charHeight } = this.getCharWidthHeight()
1040
- const { bases } = theme.palette
1041
- const colorForBase: { [key: string]: string } = {
1042
- A: bases.A.main,
1043
- C: bases.C.main,
1044
- G: bases.G.main,
1045
- T: bases.T.main,
1046
- deletion: '#808080', // gray
1047
- }
1048
-
1049
- // Display all bases softclipped off in lightened colors
1050
- if (!(seq && mismatches)) {
1051
- return
1052
- }
1053
- mismatches
1054
- .filter(mismatch => mismatch.type === 'softclip')
1055
- .forEach(mismatch => {
1056
- const len = mismatch.cliplen || 0
1057
- const s = feature.get('start')
1058
- const start = mismatch.start === 0 ? s - len : s + mismatch.start
1059
-
1060
- for (let k = 0; k < len; k += 1) {
1061
- const base = seq.charAt(k + mismatch.start)
1062
-
1063
- // If softclip length+start is longer than sequence, no need to
1064
- // continue showing base
1065
- if (!base) {
1066
- return
1067
- }
1068
-
1069
- const [leftPx, rightPx] = bpSpanPx(
1070
- start + k,
1071
- start + k + 1,
1072
- region,
1073
- bpPerPx,
1074
- )
1075
- const widthPx = Math.max(minFeatWidth, rightPx - leftPx)
1076
-
1077
- // Black accounts for IUPAC ambiguity code bases such as N that
1078
- // show in soft clipping
1079
- const baseColor = colorForBase[base] || '#000000'
1080
- ctx.fillStyle = baseColor
1081
- fillRect(ctx, leftPx, topPx, widthPx, heightPx, canvasWidth)
1082
-
1083
- if (widthPx >= charWidth && heightPx >= charHeight - 5) {
1084
- ctx.fillStyle = theme.palette.getContrastText(baseColor)
1085
- ctx.fillText(
1086
- base,
1087
- leftPx + (widthPx - charWidth) / 2 + 1,
1088
- topPx + heightPx,
1089
- )
1090
- }
1091
- }
1092
- })
1093
- }
1094
-
1095
- makeImageData({
1096
- ctx,
1097
- layoutRecords,
1098
- canvasWidth,
1099
- renderArgs,
1100
- }: {
1101
- ctx: CanvasRenderingContext2D
1102
- canvasWidth: number
1103
- layoutRecords: (LayoutFeature | null)[]
1104
- renderArgs: RenderArgsDeserializedWithFeaturesAndLayout
1105
- }) {
1106
- const {
1107
- layout,
1108
- config,
1109
- showSoftClip,
1110
- colorBy,
1111
- theme: configTheme,
1112
- } = renderArgs
1113
- const mismatchAlpha = readConfObject(config, 'mismatchAlpha')
1114
- const minSubfeatureWidth = readConfObject(config, 'minSubfeatureWidth')
1115
- const largeInsertionIndicatorScale = readConfObject(
1116
- config,
1117
- 'largeInsertionIndicatorScale',
1118
- )
1119
- const defaultColor = readConfObject(config, 'color') === '#f0f'
1120
-
1121
- const theme = createJBrowseTheme(configTheme)
1122
- const colorForBase = getColorBaseMap(theme)
1123
- const contrastForBase = getContrastBaseMap(theme)
1124
- if (!layout) {
1125
- throw new Error(`layout required`)
1126
- }
1127
- if (!layout.addRect) {
1128
- throw new Error('invalid layout object')
1129
- }
1130
- ctx.font = 'bold 10px Courier New,monospace'
1131
-
1132
- const { charWidth, charHeight } = this.getCharWidthHeight()
1133
- const drawSNPsMuted = shouldDrawSNPsMuted(colorBy?.type)
1134
- const drawIndels = shouldDrawIndels(colorBy?.type)
1135
- for (let i = 0; i < layoutRecords.length; i++) {
1136
- const feat = layoutRecords[i]
1137
- if (feat === null) {
1138
- continue
1139
- }
1140
-
1141
- this.drawAlignmentRect({
1142
- ctx,
1143
- feat,
1144
- renderArgs,
1145
- defaultColor,
1146
- colorForBase,
1147
- contrastForBase,
1148
- charWidth,
1149
- charHeight,
1150
- canvasWidth,
1151
- theme,
1152
- })
1153
- this.drawMismatches({
1154
- ctx,
1155
- feat,
1156
- renderArgs,
1157
- mismatchAlpha,
1158
- drawSNPsMuted,
1159
- drawIndels,
1160
- largeInsertionIndicatorScale,
1161
- minSubfeatureWidth,
1162
- charWidth,
1163
- charHeight,
1164
- colorForBase,
1165
- contrastForBase,
1166
- canvasWidth,
1167
- theme,
1168
- })
1169
- if (showSoftClip) {
1170
- this.drawSoftClipping({
1171
- ctx,
1172
- feat,
1173
- renderArgs,
1174
- config,
1175
- theme,
1176
- canvasWidth,
1177
- })
1178
- }
1179
- }
1180
- }
1181
-
1182
- // we perform a full layout before render as a separate method because the
1183
- // layout determines the height of the canvas that we use to render
1184
- layoutFeats(props: RenderArgsDeserializedWithFeaturesAndLayout) {
1185
- const {
1186
- layout,
1187
- features,
1188
- sortedBy,
1189
- config,
1190
- bpPerPx,
1191
- showSoftClip,
1192
- regions,
1193
- } = props
1194
- const [region] = regions
1195
- if (!layout) {
1196
- throw new Error(`layout required`)
1197
- }
1198
- if (!layout.addRect) {
1199
- throw new Error('invalid layout object')
1200
- }
1201
-
1202
- const featureMap =
1203
- sortedBy?.type && region.start === sortedBy.pos
1204
- ? sortFeature(features, sortedBy)
1205
- : features
1206
-
1207
- const heightPx = readConfObject(config, 'height')
1208
- const displayMode = readConfObject(config, 'displayMode')
1209
- return iterMap(
1210
- featureMap.values(),
1211
- feature =>
1212
- this.layoutFeature({
1213
- feature,
1214
- layout,
1215
- bpPerPx,
1216
- region,
1217
- showSoftClip,
1218
- heightPx,
1219
- displayMode,
1220
- }),
1221
- featureMap.size,
1222
- )
1223
- }
1224
-
1225
- async fetchSequence(renderProps: RenderArgsDeserialized) {
1226
- const { sessionId, regions, adapterConfig } = renderProps
1227
- const { sequenceAdapter } = adapterConfig
1228
- if (!sequenceAdapter) {
1229
- return undefined
1230
- }
1231
- const { dataAdapter } = await getAdapter(
1232
- this.pluginManager,
1233
- sessionId,
1234
- sequenceAdapter,
1235
- )
1236
- const [region] = regions
1237
- return fetchSequence(region, dataAdapter as BaseFeatureDataAdapter)
1238
- }
1239
-
1240
75
  async render(renderProps: RenderArgsDeserialized) {
1241
76
  const features = await this.getFeatures(renderProps)
1242
77
  const layout = this.createLayoutInWorker(renderProps)
1243
78
  const { regions, bpPerPx } = renderProps
1244
79
  const [region] = regions
1245
80
 
1246
- const layoutRecords = this.layoutFeats({
81
+ const layoutRecords = layoutFeats({
1247
82
  ...renderProps,
1248
83
  features,
1249
84
  layout,
@@ -1255,15 +90,13 @@ export default class PileupRenderer extends BoxRendererType {
1255
90
  features.size && shouldFetchReferenceSequence(renderProps.colorBy?.type)
1256
91
  ? await this.fetchSequence(renderProps)
1257
92
  : undefined
1258
- const { end, start } = region
1259
-
1260
- const width = (end - start) / bpPerPx
93
+ const width = (region.end - region.start) / bpPerPx
1261
94
  const height = Math.max(layout.getTotalHeight(), 1)
1262
95
  const Color = await import('color').then(f => f.default)
1263
96
  const res = await renderToAbstractCanvas(width, height, renderProps, ctx =>
1264
- this.makeImageData({
97
+ makeImageData({
1265
98
  ctx,
1266
- layoutRecords,
99
+ layoutRecords: layoutRecords.filter(notEmpty),
1267
100
  canvasWidth: width,
1268
101
  renderArgs: {
1269
102
  ...renderProps,