@jbrowse/plugin-dotplot-view 2.6.1

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 (263) hide show
  1. package/LICENSE +201 -0
  2. package/dist/ComparativeRenderer/index.d.ts +27 -0
  3. package/dist/ComparativeRenderer/index.js +59 -0
  4. package/dist/ComparativeRenderer/index.js.map +1 -0
  5. package/dist/DotplotDisplay/components/DotplotDisplay.d.ts +8 -0
  6. package/dist/DotplotDisplay/components/DotplotDisplay.js +24 -0
  7. package/dist/DotplotDisplay/components/DotplotDisplay.js.map +1 -0
  8. package/dist/DotplotDisplay/index.d.ts +12 -0
  9. package/dist/DotplotDisplay/index.js +48 -0
  10. package/dist/DotplotDisplay/index.js.map +1 -0
  11. package/dist/DotplotDisplay/renderDotplotBlock.d.ts +11 -0
  12. package/dist/DotplotDisplay/renderDotplotBlock.js +57 -0
  13. package/dist/DotplotDisplay/renderDotplotBlock.js.map +1 -0
  14. package/dist/DotplotDisplay/stateModelFactory.d.ts +138 -0
  15. package/dist/DotplotDisplay/stateModelFactory.js +165 -0
  16. package/dist/DotplotDisplay/stateModelFactory.js.map +1 -0
  17. package/dist/DotplotReadVsRef/DotplotReadVsRef.d.ts +3 -0
  18. package/dist/DotplotReadVsRef/DotplotReadVsRef.js +102 -0
  19. package/dist/DotplotReadVsRef/DotplotReadVsRef.js.map +1 -0
  20. package/dist/DotplotReadVsRef/index.d.ts +2 -0
  21. package/dist/DotplotReadVsRef/index.js +42 -0
  22. package/dist/DotplotReadVsRef/index.js.map +1 -0
  23. package/dist/DotplotRenderer/ComparativeRenderRpc.d.ts +27 -0
  24. package/dist/DotplotRenderer/ComparativeRenderRpc.js +59 -0
  25. package/dist/DotplotRenderer/ComparativeRenderRpc.js.map +1 -0
  26. package/dist/DotplotRenderer/DotplotRenderer.d.ts +69 -0
  27. package/dist/DotplotRenderer/DotplotRenderer.js +274 -0
  28. package/dist/DotplotRenderer/DotplotRenderer.js.map +1 -0
  29. package/dist/DotplotRenderer/components/DotplotRendering.d.ts +5 -0
  30. package/dist/DotplotRenderer/components/DotplotRendering.js +13 -0
  31. package/dist/DotplotRenderer/components/DotplotRendering.js.map +1 -0
  32. package/dist/DotplotRenderer/configSchema.d.ts +61 -0
  33. package/dist/DotplotRenderer/configSchema.js +83 -0
  34. package/dist/DotplotRenderer/configSchema.js.map +1 -0
  35. package/dist/DotplotRenderer/index.d.ts +3 -0
  36. package/dist/DotplotRenderer/index.js +17 -0
  37. package/dist/DotplotRenderer/index.js.map +1 -0
  38. package/dist/DotplotView/1dview.d.ts +307 -0
  39. package/dist/DotplotView/1dview.js +95 -0
  40. package/dist/DotplotView/1dview.js.map +1 -0
  41. package/dist/DotplotView/blockTypes.d.ts +61 -0
  42. package/dist/DotplotView/blockTypes.js +117 -0
  43. package/dist/DotplotView/blockTypes.js.map +1 -0
  44. package/dist/DotplotView/components/Axes.d.ts +14 -0
  45. package/dist/DotplotView/components/Axes.js +127 -0
  46. package/dist/DotplotView/components/Axes.js.map +1 -0
  47. package/dist/DotplotView/components/CursorIcon.d.ts +4 -0
  48. package/dist/DotplotView/components/CursorIcon.js +19 -0
  49. package/dist/DotplotView/components/CursorIcon.js.map +1 -0
  50. package/dist/DotplotView/components/DotplotTooltip.d.ts +19 -0
  51. package/dist/DotplotView/components/DotplotTooltip.js +128 -0
  52. package/dist/DotplotView/components/DotplotTooltip.js.map +1 -0
  53. package/dist/DotplotView/components/DotplotView.d.ts +6 -0
  54. package/dist/DotplotView/components/DotplotView.js +272 -0
  55. package/dist/DotplotView/components/DotplotView.js.map +1 -0
  56. package/dist/DotplotView/components/DotplotWarnings.d.ts +6 -0
  57. package/dist/DotplotView/components/DotplotWarnings.js +40 -0
  58. package/dist/DotplotView/components/DotplotWarnings.js.map +1 -0
  59. package/dist/DotplotView/components/ExportSvgDialog.d.ts +8 -0
  60. package/dist/DotplotView/components/ExportSvgDialog.js +76 -0
  61. package/dist/DotplotView/components/ExportSvgDialog.js.map +1 -0
  62. package/dist/DotplotView/components/Grid.d.ts +10 -0
  63. package/dist/DotplotView/components/Grid.js +60 -0
  64. package/dist/DotplotView/components/Grid.js.map +1 -0
  65. package/dist/DotplotView/components/Header.d.ts +10 -0
  66. package/dist/DotplotView/components/Header.js +168 -0
  67. package/dist/DotplotView/components/Header.js.map +1 -0
  68. package/dist/DotplotView/components/ImportCustomTrack.d.ts +11 -0
  69. package/dist/DotplotView/components/ImportCustomTrack.js +180 -0
  70. package/dist/DotplotView/components/ImportCustomTrack.js.map +1 -0
  71. package/dist/DotplotView/components/ImportForm.d.ts +6 -0
  72. package/dist/DotplotView/components/ImportForm.js +121 -0
  73. package/dist/DotplotView/components/ImportForm.js.map +1 -0
  74. package/dist/DotplotView/components/ImportSyntenyTrackSelector.d.ts +9 -0
  75. package/dist/DotplotView/components/ImportSyntenyTrackSelector.js +69 -0
  76. package/dist/DotplotView/components/ImportSyntenyTrackSelector.js.map +1 -0
  77. package/dist/DotplotView/components/PanButtons.d.ts +6 -0
  78. package/dist/DotplotView/components/PanButtons.js +60 -0
  79. package/dist/DotplotView/components/PanButtons.js.map +1 -0
  80. package/dist/DotplotView/components/WarningDialog.d.ts +16 -0
  81. package/dist/DotplotView/components/WarningDialog.js +41 -0
  82. package/dist/DotplotView/components/WarningDialog.js.map +1 -0
  83. package/dist/DotplotView/components/util.d.ts +19 -0
  84. package/dist/DotplotView/components/util.js +90 -0
  85. package/dist/DotplotView/components/util.js.map +1 -0
  86. package/dist/DotplotView/index.d.ts +2 -0
  87. package/dist/DotplotView/index.js +44 -0
  88. package/dist/DotplotView/index.js.map +1 -0
  89. package/dist/DotplotView/model.d.ts +616 -0
  90. package/dist/DotplotView/model.js +647 -0
  91. package/dist/DotplotView/model.js.map +1 -0
  92. package/dist/DotplotView/svgcomponents/SVGBackground.d.ts +5 -0
  93. package/dist/DotplotView/svgcomponents/SVGBackground.js +13 -0
  94. package/dist/DotplotView/svgcomponents/SVGBackground.js.map +1 -0
  95. package/dist/DotplotView/svgcomponents/SVGDotplotView.d.ts +2 -0
  96. package/dist/DotplotView/svgcomponents/SVGDotplotView.js +47 -0
  97. package/dist/DotplotView/svgcomponents/SVGDotplotView.js.map +1 -0
  98. package/dist/LaunchDotplotView.d.ts +2 -0
  99. package/dist/LaunchDotplotView.js +45 -0
  100. package/dist/LaunchDotplotView.js.map +1 -0
  101. package/dist/ServerSideRenderedBlockContent.d.ts +12 -0
  102. package/dist/ServerSideRenderedBlockContent.js +87 -0
  103. package/dist/ServerSideRenderedBlockContent.js.map +1 -0
  104. package/dist/ServerSideSyntenyRendering.d.ts +23 -0
  105. package/dist/ServerSideSyntenyRendering.js +54 -0
  106. package/dist/ServerSideSyntenyRendering.js.map +1 -0
  107. package/dist/index.d.ts +7 -0
  108. package/dist/index.js +44 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/util.d.ts +9 -0
  111. package/dist/util.js +9 -0
  112. package/dist/util.js.map +1 -0
  113. package/esm/ComparativeRenderer/index.d.ts +27 -0
  114. package/esm/ComparativeRenderer/index.js +53 -0
  115. package/esm/ComparativeRenderer/index.js.map +1 -0
  116. package/esm/DotplotDisplay/components/DotplotDisplay.d.ts +8 -0
  117. package/esm/DotplotDisplay/components/DotplotDisplay.js +19 -0
  118. package/esm/DotplotDisplay/components/DotplotDisplay.js.map +1 -0
  119. package/esm/DotplotDisplay/index.d.ts +12 -0
  120. package/esm/DotplotDisplay/index.js +41 -0
  121. package/esm/DotplotDisplay/index.js.map +1 -0
  122. package/esm/DotplotDisplay/renderDotplotBlock.d.ts +11 -0
  123. package/esm/DotplotDisplay/renderDotplotBlock.js +49 -0
  124. package/esm/DotplotDisplay/renderDotplotBlock.js.map +1 -0
  125. package/esm/DotplotDisplay/stateModelFactory.d.ts +138 -0
  126. package/esm/DotplotDisplay/stateModelFactory.js +158 -0
  127. package/esm/DotplotDisplay/stateModelFactory.js.map +1 -0
  128. package/esm/DotplotReadVsRef/DotplotReadVsRef.d.ts +3 -0
  129. package/esm/DotplotReadVsRef/DotplotReadVsRef.js +98 -0
  130. package/esm/DotplotReadVsRef/DotplotReadVsRef.js.map +1 -0
  131. package/esm/DotplotReadVsRef/index.d.ts +2 -0
  132. package/esm/DotplotReadVsRef/index.js +36 -0
  133. package/esm/DotplotReadVsRef/index.js.map +1 -0
  134. package/esm/DotplotRenderer/ComparativeRenderRpc.d.ts +27 -0
  135. package/esm/DotplotRenderer/ComparativeRenderRpc.js +53 -0
  136. package/esm/DotplotRenderer/ComparativeRenderRpc.js.map +1 -0
  137. package/esm/DotplotRenderer/DotplotRenderer.d.ts +69 -0
  138. package/esm/DotplotRenderer/DotplotRenderer.js +268 -0
  139. package/esm/DotplotRenderer/DotplotRenderer.js.map +1 -0
  140. package/esm/DotplotRenderer/components/DotplotRendering.d.ts +5 -0
  141. package/esm/DotplotRenderer/components/DotplotRendering.js +8 -0
  142. package/esm/DotplotRenderer/components/DotplotRendering.js.map +1 -0
  143. package/esm/DotplotRenderer/configSchema.d.ts +61 -0
  144. package/esm/DotplotRenderer/configSchema.js +81 -0
  145. package/esm/DotplotRenderer/configSchema.js.map +1 -0
  146. package/esm/DotplotRenderer/index.d.ts +3 -0
  147. package/esm/DotplotRenderer/index.js +12 -0
  148. package/esm/DotplotRenderer/index.js.map +1 -0
  149. package/esm/DotplotView/1dview.d.ts +307 -0
  150. package/esm/DotplotView/1dview.js +87 -0
  151. package/esm/DotplotView/1dview.js.map +1 -0
  152. package/esm/DotplotView/blockTypes.d.ts +61 -0
  153. package/esm/DotplotView/blockTypes.js +109 -0
  154. package/esm/DotplotView/blockTypes.js.map +1 -0
  155. package/esm/DotplotView/components/Axes.d.ts +14 -0
  156. package/esm/DotplotView/components/Axes.js +121 -0
  157. package/esm/DotplotView/components/Axes.js.map +1 -0
  158. package/esm/DotplotView/components/CursorIcon.d.ts +4 -0
  159. package/esm/DotplotView/components/CursorIcon.js +11 -0
  160. package/esm/DotplotView/components/CursorIcon.js.map +1 -0
  161. package/esm/DotplotView/components/DotplotTooltip.d.ts +19 -0
  162. package/esm/DotplotView/components/DotplotTooltip.js +101 -0
  163. package/esm/DotplotView/components/DotplotTooltip.js.map +1 -0
  164. package/esm/DotplotView/components/DotplotView.d.ts +6 -0
  165. package/esm/DotplotView/components/DotplotView.js +244 -0
  166. package/esm/DotplotView/components/DotplotView.js.map +1 -0
  167. package/esm/DotplotView/components/DotplotWarnings.d.ts +6 -0
  168. package/esm/DotplotView/components/DotplotWarnings.js +15 -0
  169. package/esm/DotplotView/components/DotplotWarnings.js.map +1 -0
  170. package/esm/DotplotView/components/ExportSvgDialog.d.ts +8 -0
  171. package/esm/DotplotView/components/ExportSvgDialog.js +50 -0
  172. package/esm/DotplotView/components/ExportSvgDialog.js.map +1 -0
  173. package/esm/DotplotView/components/Grid.d.ts +10 -0
  174. package/esm/DotplotView/components/Grid.js +53 -0
  175. package/esm/DotplotView/components/Grid.js.map +1 -0
  176. package/esm/DotplotView/components/Header.d.ts +10 -0
  177. package/esm/DotplotView/components/Header.js +140 -0
  178. package/esm/DotplotView/components/Header.js.map +1 -0
  179. package/esm/DotplotView/components/ImportCustomTrack.d.ts +11 -0
  180. package/esm/DotplotView/components/ImportCustomTrack.js +152 -0
  181. package/esm/DotplotView/components/ImportCustomTrack.js.map +1 -0
  182. package/esm/DotplotView/components/ImportForm.d.ts +6 -0
  183. package/esm/DotplotView/components/ImportForm.js +93 -0
  184. package/esm/DotplotView/components/ImportForm.js.map +1 -0
  185. package/esm/DotplotView/components/ImportSyntenyTrackSelector.d.ts +9 -0
  186. package/esm/DotplotView/components/ImportSyntenyTrackSelector.js +44 -0
  187. package/esm/DotplotView/components/ImportSyntenyTrackSelector.js.map +1 -0
  188. package/esm/DotplotView/components/PanButtons.d.ts +6 -0
  189. package/esm/DotplotView/components/PanButtons.js +55 -0
  190. package/esm/DotplotView/components/PanButtons.js.map +1 -0
  191. package/esm/DotplotView/components/WarningDialog.d.ts +16 -0
  192. package/esm/DotplotView/components/WarningDialog.js +36 -0
  193. package/esm/DotplotView/components/WarningDialog.js.map +1 -0
  194. package/esm/DotplotView/components/util.d.ts +19 -0
  195. package/esm/DotplotView/components/util.js +83 -0
  196. package/esm/DotplotView/components/util.js.map +1 -0
  197. package/esm/DotplotView/index.d.ts +2 -0
  198. package/esm/DotplotView/index.js +15 -0
  199. package/esm/DotplotView/index.js.map +1 -0
  200. package/esm/DotplotView/model.d.ts +616 -0
  201. package/esm/DotplotView/model.js +616 -0
  202. package/esm/DotplotView/model.js.map +1 -0
  203. package/esm/DotplotView/svgcomponents/SVGBackground.d.ts +5 -0
  204. package/esm/DotplotView/svgcomponents/SVGBackground.js +7 -0
  205. package/esm/DotplotView/svgcomponents/SVGBackground.js.map +1 -0
  206. package/esm/DotplotView/svgcomponents/SVGDotplotView.d.ts +2 -0
  207. package/esm/DotplotView/svgcomponents/SVGDotplotView.js +40 -0
  208. package/esm/DotplotView/svgcomponents/SVGDotplotView.js.map +1 -0
  209. package/esm/LaunchDotplotView.d.ts +2 -0
  210. package/esm/LaunchDotplotView.js +42 -0
  211. package/esm/LaunchDotplotView.js.map +1 -0
  212. package/esm/ServerSideRenderedBlockContent.d.ts +12 -0
  213. package/esm/ServerSideRenderedBlockContent.js +62 -0
  214. package/esm/ServerSideRenderedBlockContent.js.map +1 -0
  215. package/esm/ServerSideSyntenyRendering.d.ts +23 -0
  216. package/esm/ServerSideSyntenyRendering.js +29 -0
  217. package/esm/ServerSideSyntenyRendering.js.map +1 -0
  218. package/esm/index.d.ts +7 -0
  219. package/esm/index.js +38 -0
  220. package/esm/index.js.map +1 -0
  221. package/esm/util.d.ts +9 -0
  222. package/esm/util.js +5 -0
  223. package/esm/util.js.map +1 -0
  224. package/package.json +69 -0
  225. package/src/ComparativeRenderer/index.ts +87 -0
  226. package/src/DotplotDisplay/components/DotplotDisplay.tsx +34 -0
  227. package/src/DotplotDisplay/index.ts +48 -0
  228. package/src/DotplotDisplay/renderDotplotBlock.ts +60 -0
  229. package/src/DotplotDisplay/stateModelFactory.tsx +196 -0
  230. package/src/DotplotReadVsRef/DotplotReadVsRef.ts +115 -0
  231. package/src/DotplotReadVsRef/index.ts +50 -0
  232. package/src/DotplotRenderer/ComparativeRenderRpc.ts +87 -0
  233. package/src/DotplotRenderer/DotplotRenderer.ts +328 -0
  234. package/src/DotplotRenderer/__image_snapshots__/linear-synteny-renderer-test-ts-test-rendering-a-simple-synteny-from-fake-data-1-snap.png +0 -0
  235. package/src/DotplotRenderer/components/DotplotRendering.tsx +12 -0
  236. package/src/DotplotRenderer/configSchema.ts +92 -0
  237. package/src/DotplotRenderer/index.ts +16 -0
  238. package/src/DotplotView/1dview.ts +98 -0
  239. package/src/DotplotView/blockTypes.ts +140 -0
  240. package/src/DotplotView/components/Axes.tsx +246 -0
  241. package/src/DotplotView/components/CursorIcon.tsx +24 -0
  242. package/src/DotplotView/components/DotplotTooltip.tsx +163 -0
  243. package/src/DotplotView/components/DotplotView.tsx +348 -0
  244. package/src/DotplotView/components/DotplotWarnings.tsx +26 -0
  245. package/src/DotplotView/components/ExportSvgDialog.tsx +129 -0
  246. package/src/DotplotView/components/Grid.tsx +112 -0
  247. package/src/DotplotView/components/Header.tsx +182 -0
  248. package/src/DotplotView/components/ImportCustomTrack.tsx +262 -0
  249. package/src/DotplotView/components/ImportForm.tsx +209 -0
  250. package/src/DotplotView/components/ImportSyntenyTrackSelector.tsx +90 -0
  251. package/src/DotplotView/components/PanButtons.tsx +93 -0
  252. package/src/DotplotView/components/WarningDialog.tsx +74 -0
  253. package/src/DotplotView/components/util.ts +118 -0
  254. package/src/DotplotView/index.ts +16 -0
  255. package/src/DotplotView/model.test.ts +17 -0
  256. package/src/DotplotView/model.ts +719 -0
  257. package/src/DotplotView/svgcomponents/SVGBackground.tsx +21 -0
  258. package/src/DotplotView/svgcomponents/SVGDotplotView.tsx +68 -0
  259. package/src/LaunchDotplotView.ts +63 -0
  260. package/src/ServerSideRenderedBlockContent.tsx +86 -0
  261. package/src/ServerSideSyntenyRendering.tsx +54 -0
  262. package/src/index.ts +41 -0
  263. package/src/util.ts +14 -0
@@ -0,0 +1,328 @@
1
+ import {
2
+ readConfObject,
3
+ AnyConfigurationModel,
4
+ } from '@jbrowse/core/configuration'
5
+ import {
6
+ renameRegionsIfNeeded,
7
+ renderToAbstractCanvas,
8
+ Region,
9
+ Feature,
10
+ } from '@jbrowse/core/util'
11
+ import { bpToPx } from '@jbrowse/core/util/Base1DUtils'
12
+ import { getSnapshot } from 'mobx-state-tree'
13
+ import ComparativeRenderer, {
14
+ RenderArgsDeserialized,
15
+ RenderArgs,
16
+ } from '@jbrowse/core/pluggableElementTypes/renderers/ComparativeServerSideRendererType'
17
+ import { MismatchParser } from '@jbrowse/plugin-alignments'
18
+
19
+ // locals
20
+ import { Dotplot1DView, Dotplot1DViewModel } from '../DotplotView/model'
21
+ import { createJBrowseTheme } from '@jbrowse/core/ui'
22
+
23
+ const { parseCigar } = MismatchParser
24
+
25
+ export interface DotplotRenderArgsDeserialized extends RenderArgsDeserialized {
26
+ height: number
27
+ width: number
28
+ highResolutionScaling: number
29
+ view: {
30
+ hview: Dotplot1DViewModel
31
+ vview: Dotplot1DViewModel
32
+ }
33
+ }
34
+
35
+ interface DotplotRenderArgs extends RenderArgs {
36
+ adapterConfig: AnyConfigurationModel
37
+ sessionId: string
38
+ view: {
39
+ hview: { displayedRegions: Region[] }
40
+ vview: { displayedRegions: Region[] }
41
+ }
42
+ }
43
+
44
+ const r = 'fell outside of range due to CIGAR string'
45
+ const lt = '(less than min coordinate of feature)'
46
+ const gt = '(greater than max coordinate of feature)'
47
+ const fudgeFactor = 1 // allow 1px fuzzyness before warn
48
+
49
+ function drawCir(ctx: CanvasRenderingContext2D, x: number, y: number, r = 1) {
50
+ ctx.beginPath()
51
+ ctx.arc(x, y, r / 2, 0, 2 * Math.PI)
52
+ ctx.fill()
53
+ }
54
+
55
+ export default class DotplotRenderer extends ComparativeRenderer {
56
+ supportsSVG = true
57
+
58
+ async renameRegionsIfNeeded(args: DotplotRenderArgs) {
59
+ const pm = this.pluginManager
60
+ const assemblyManager = pm.rootModel?.session?.assemblyManager
61
+
62
+ const { view, sessionId, adapterConfig } = args
63
+
64
+ async function process(regions?: Region[]) {
65
+ if (!assemblyManager) {
66
+ throw new Error('No assembly manager provided')
67
+ }
68
+ const result = await renameRegionsIfNeeded(assemblyManager, {
69
+ sessionId,
70
+ adapterConfig,
71
+ regions,
72
+ })
73
+ return result.regions
74
+ }
75
+
76
+ view.hview.displayedRegions = await process(view.hview.displayedRegions)
77
+ view.vview.displayedRegions = await process(view.vview.displayedRegions)
78
+
79
+ return args
80
+ }
81
+
82
+ async drawDotplot(
83
+ ctx: CanvasRenderingContext2D,
84
+ props: DotplotRenderArgsDeserialized & { views: Dotplot1DViewModel[] },
85
+ ) {
86
+ const { config, views, height, drawCigar, theme } = props
87
+ const color = readConfObject(config, 'color')
88
+ const posColor = readConfObject(config, 'posColor')
89
+ const negColor = readConfObject(config, 'negColor')
90
+ const colorBy = readConfObject(config, 'colorBy')
91
+ const lineWidth = readConfObject(config, 'lineWidth')
92
+ const thresholds = readConfObject(config, 'thresholds')
93
+ const palette = readConfObject(config, 'thresholdsPalette')
94
+ const isCallback = config.color.isCallback
95
+ const [hview, vview] = views
96
+ const db1 = hview.dynamicBlocks.contentBlocks[0]?.offsetPx
97
+ const db2 = vview.dynamicBlocks.contentBlocks[0]?.offsetPx
98
+ const warnings = [] as { message: string; effect: string }[]
99
+ ctx.lineWidth = lineWidth
100
+
101
+ // we operate on snapshots of these attributes of the hview/vview because
102
+ // it is significantly faster than accessing the mobx objects
103
+ const { bpPerPx: hBpPerPx } = hview
104
+ const { bpPerPx: vBpPerPx } = vview
105
+
106
+ function clampWithWarnX(
107
+ num: number,
108
+ min: number,
109
+ max: number,
110
+ feature: Feature,
111
+ ) {
112
+ const strand = feature.get('strand') || 1
113
+ if (strand === -1) {
114
+ ;[max, min] = [min, max]
115
+ }
116
+ if (num < min - fudgeFactor) {
117
+ let start = feature.get('start')
118
+ let end = feature.get('end')
119
+ const refName = feature.get('refName')
120
+ if (strand === -1) {
121
+ ;[end, start] = [start, end]
122
+ }
123
+
124
+ warnings.push({
125
+ message: `feature at (X ${refName}:${start}-${end}) ${r} ${lt}`,
126
+ effect: 'clipped the feature',
127
+ })
128
+ return min
129
+ }
130
+ if (num > max + fudgeFactor) {
131
+ const strand = feature.get('strand') || 1
132
+ const start = strand === 1 ? feature.get('start') : feature.get('end')
133
+ const end = strand === 1 ? feature.get('end') : feature.get('start')
134
+ const refName = feature.get('refName')
135
+
136
+ warnings.push({
137
+ message: `feature at (X ${refName}:${start}-${end}) ${r} ${gt}`,
138
+ effect: 'clipped the feature',
139
+ })
140
+ return max
141
+ }
142
+ return num
143
+ }
144
+
145
+ function clampWithWarnY(
146
+ num: number,
147
+ min: number,
148
+ max: number,
149
+ feature: Feature,
150
+ ) {
151
+ if (num < min - fudgeFactor) {
152
+ const mate = feature.get('mate')
153
+ const { refName, start, end } = mate
154
+ warnings.push({
155
+ message: `feature at (Y ${refName}:${start}-${end}) ${r} ${lt}`,
156
+ effect: 'clipped the feature',
157
+ })
158
+ return min
159
+ }
160
+ if (num > max + fudgeFactor) {
161
+ const mate = feature.get('mate')
162
+ const { refName, start, end } = mate
163
+
164
+ warnings.push({
165
+ message: `feature at (Y ${refName}:${start}-${end}) ${r} ${gt}`,
166
+ effect: 'clipped the feature',
167
+ })
168
+ return max
169
+ }
170
+ return num
171
+ }
172
+
173
+ const hsnap = {
174
+ ...getSnapshot(hview),
175
+ staticBlocks: hview.staticBlocks,
176
+ width: hview.width,
177
+ }
178
+ const vsnap = {
179
+ ...getSnapshot(vview),
180
+ staticBlocks: vview.staticBlocks,
181
+ width: vview.width,
182
+ }
183
+ const t = createJBrowseTheme(theme)
184
+ hview.features?.forEach(feature => {
185
+ const strand = feature.get('strand') || 1
186
+ const start = strand === 1 ? feature.get('start') : feature.get('end')
187
+ const end = strand === 1 ? feature.get('end') : feature.get('start')
188
+ const refName = feature.get('refName')
189
+ const mate = feature.get('mate')
190
+ const mateRef = mate.refName
191
+
192
+ let r
193
+ if (colorBy === 'identity') {
194
+ const identity = feature.get('identity')
195
+ for (let i = 0; i < thresholds.length; i++) {
196
+ if (identity > +thresholds[i]) {
197
+ r = palette[i]
198
+ break
199
+ }
200
+ }
201
+ } else if (colorBy === 'meanQueryIdentity') {
202
+ r = `hsl(${feature.get('meanScore') * 200},100%,40%)`
203
+ } else if (colorBy === 'mappingQuality') {
204
+ r = `hsl(${feature.get('mappingQual')},100%,40%)`
205
+ } else if (colorBy === 'strand') {
206
+ r = strand === -1 ? negColor : posColor
207
+ } else if (colorBy === 'default') {
208
+ r = isCallback
209
+ ? readConfObject(config, 'color', { feature })
210
+ : color === '#f0f'
211
+ ? t.palette.text.primary
212
+ : color
213
+ }
214
+ ctx.fillStyle = r
215
+ ctx.strokeStyle = r
216
+
217
+ const b10 = bpToPx({ self: hsnap, refName, coord: start })
218
+ const b20 = bpToPx({ self: hsnap, refName, coord: end })
219
+ const e10 = bpToPx({ self: vsnap, refName: mateRef, coord: mate.start })
220
+ const e20 = bpToPx({ self: vsnap, refName: mateRef, coord: mate.end })
221
+ if (
222
+ b10 !== undefined &&
223
+ b20 !== undefined &&
224
+ e10 !== undefined &&
225
+ e20 !== undefined
226
+ ) {
227
+ const b1 = b10.offsetPx - db1
228
+ const b2 = b20.offsetPx - db1
229
+ const e1 = e10.offsetPx - db2
230
+ const e2 = e20.offsetPx - db2
231
+ if (Math.abs(b1 - b2) <= 4 && Math.abs(e1 - e2) <= 4) {
232
+ drawCir(ctx, b1, height - e1, lineWidth)
233
+ } else {
234
+ let currX = b1
235
+ let currY = e1
236
+ const cigar = feature.get('CIGAR')
237
+ if (drawCigar && cigar) {
238
+ const cigarOps = parseCigar(cigar)
239
+
240
+ ctx.beginPath()
241
+ ctx.moveTo(currX, height - currY)
242
+
243
+ for (let i = 0; i < cigarOps.length; i += 2) {
244
+ const val = +cigarOps[i]
245
+ const op = cigarOps[i + 1]
246
+ if (op === 'M' || op === '=' || op === 'X') {
247
+ currX += (val / hBpPerPx) * strand
248
+ currY += val / vBpPerPx
249
+ } else if (op === 'D' || op === 'N') {
250
+ currX += (val / hBpPerPx) * strand
251
+ } else if (op === 'I') {
252
+ currY += val / vBpPerPx
253
+ }
254
+ currX = clampWithWarnX(currX, b1, b2, feature)
255
+ currY = clampWithWarnY(currY, e1, e2, feature)
256
+ ctx.lineTo(currX, height - currY)
257
+ }
258
+
259
+ ctx.stroke()
260
+ } else {
261
+ ctx.beginPath()
262
+ ctx.moveTo(b1, height - e1)
263
+ ctx.lineTo(b2, height - e2)
264
+ ctx.stroke()
265
+ }
266
+ }
267
+ } else {
268
+ if (warnings.length <= 5) {
269
+ if (b10 === undefined || b20 === undefined) {
270
+ warnings.push({
271
+ message: `feature at (X ${refName}:${start}-${end}) not plotted, fell outside of range`,
272
+ effect: 'feature not rendered',
273
+ })
274
+ } else {
275
+ warnings.push({
276
+ message: `feature at (Y ${mateRef}:${mate.start}-${mate.end}) not plotted, fell outside of range`,
277
+ effect: 'feature not rendered',
278
+ })
279
+ }
280
+ }
281
+ }
282
+ })
283
+
284
+ return { warnings }
285
+ }
286
+
287
+ async render(renderProps: DotplotRenderArgsDeserialized) {
288
+ const {
289
+ width,
290
+ height,
291
+ view: { hview, vview },
292
+ } = renderProps
293
+ const dimensions = [width, height]
294
+ const views = [hview, vview].map((snap, idx) => {
295
+ const view = Dotplot1DView.create(snap)
296
+ view.setVolatileWidth(dimensions[idx])
297
+ return view
298
+ })
299
+ const target = views[0]
300
+ const feats = await this.getFeatures({
301
+ ...renderProps,
302
+ regions: target.dynamicBlocks.contentBlocks,
303
+ })
304
+ target.setFeatures(feats)
305
+
306
+ const ret = await renderToAbstractCanvas(width, height, renderProps, ctx =>
307
+ this.drawDotplot(ctx, { ...renderProps, views }),
308
+ )
309
+
310
+ const results = await super.render({
311
+ ...renderProps,
312
+ ...ret,
313
+ height,
314
+ width,
315
+ })
316
+
317
+ return {
318
+ ...results,
319
+ ...ret,
320
+ height,
321
+ width,
322
+ offsetX: views[0].dynamicBlocks.blocks[0]?.offsetPx || 0,
323
+ offsetY: views[1].dynamicBlocks.blocks[0]?.offsetPx || 0,
324
+ bpPerPxX: views[0].bpPerPx,
325
+ bpPerPxY: views[1].bpPerPx,
326
+ }
327
+ }
328
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react'
2
+ import { PrerenderedCanvas } from '@jbrowse/core/ui'
3
+ import { observer } from 'mobx-react'
4
+
5
+ // locals
6
+ import { DotplotRenderArgsDeserialized } from '../DotplotRenderer'
7
+
8
+ function DotplotRendering(props: DotplotRenderArgsDeserialized) {
9
+ return <PrerenderedCanvas {...props} />
10
+ }
11
+
12
+ export default observer(DotplotRendering)
@@ -0,0 +1,92 @@
1
+ import { ConfigurationSchema } from '@jbrowse/core/configuration'
2
+ import { types } from 'mobx-state-tree'
3
+
4
+ /**
5
+ * #config DotplotRenderer
6
+ * #category renderer
7
+ */
8
+ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
9
+
10
+ export default ConfigurationSchema(
11
+ 'DotplotRenderer',
12
+ {
13
+ /**
14
+ * #slot
15
+ */
16
+ color: {
17
+ type: 'color',
18
+ description:
19
+ 'the color of each feature in a synteny, used with colorBy:default',
20
+ defaultValue: '#f0f',
21
+ contextVariable: ['feature'],
22
+ },
23
+
24
+ /**
25
+ * #slot
26
+ */
27
+ posColor: {
28
+ type: 'color',
29
+ description: 'the color for forward alignments, used with colorBy:strand',
30
+ defaultValue: 'blue',
31
+ },
32
+ /**
33
+ * #slot
34
+ */
35
+ negColor: {
36
+ type: 'color',
37
+ description: 'the color for reverse alignments, used with colorBy:strand',
38
+ defaultValue: 'red',
39
+ },
40
+
41
+ /**
42
+ * #slot
43
+ */
44
+ lineWidth: {
45
+ type: 'number',
46
+ description: 'width of the lines to be drawn',
47
+ defaultValue: 2.5, // 2.5 is similar to D-GENIES
48
+ },
49
+
50
+ /**
51
+ * #slot
52
+ */
53
+ colorBy: {
54
+ type: 'stringEnum',
55
+ model: types.enumeration('colorBy', [
56
+ 'identity',
57
+ 'meanQueryIdentity',
58
+ 'mappingQuality',
59
+ 'strand',
60
+ 'default',
61
+ ]),
62
+ description: `Color by options:<br/>
63
+ <ul>
64
+ <li>"identity" - the identity of the particular hit, similar to D-GENIES, use the other config slots 'thresholds' and 'thresholdsPalette' to define colors for this setting</li>
65
+ <li>"meanQueryIdentity" - calculates the weighted mean identity (weighted by alignment length) of all the hits that the query maps to (e.g. if the query is split aligned to many target, uses their weighted mean. can help show patterns of more related and distant synteny after WGD)</li>
66
+ <li>"mappingQuality" - uses mapping quality from PAF, some adapters don't have this setting</li>
67
+ <li>"strand" - colors negative alignments with negColor and positive alignments with posColor</li>
68
+ <li>"default" - uses the 'color' config slot</li>
69
+ </ul>`,
70
+ defaultValue: 'default',
71
+ },
72
+
73
+ /**
74
+ * #slot
75
+ */
76
+ thresholdsPalette: {
77
+ type: 'stringArray',
78
+ defaultValue: ['#094b09', '#2ebd40', '#d5670b', '#ffd84b'],
79
+ description: 'threshold colors, used with colorBy:identity',
80
+ },
81
+
82
+ /**
83
+ * #slot
84
+ */
85
+ thresholds: {
86
+ type: 'stringArray',
87
+ defaultValue: ['0.75', '0.5', '0.25', '0'],
88
+ description: 'threshold breakpoints, used with colorBy:identity',
89
+ },
90
+ },
91
+ { explicitlyTyped: true },
92
+ )
@@ -0,0 +1,16 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager'
2
+ import ReactComponent from './components/DotplotRendering'
3
+ import DotplotRenderer from './DotplotRenderer'
4
+ import configSchema from './configSchema'
5
+
6
+ export default (pluginManager: PluginManager) => {
7
+ pluginManager.addRendererType(
8
+ () =>
9
+ new DotplotRenderer({
10
+ name: 'DotplotRenderer',
11
+ configSchema: configSchema,
12
+ ReactComponent,
13
+ pluginManager,
14
+ }),
15
+ )
16
+ }
@@ -0,0 +1,98 @@
1
+ import { getParent, Instance } from 'mobx-state-tree'
2
+ import { observable } from 'mobx'
3
+ import Base1DView from '@jbrowse/core/util/Base1DViewModel'
4
+ import calculateDynamicBlocks from '@jbrowse/core/util/calculateDynamicBlocks'
5
+
6
+ /**
7
+ * #stateModel Dotplot1DView
8
+ * ref https://mobx-state-tree.js.org/concepts/volatiles on volatile state used here
9
+ */
10
+ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
11
+
12
+ const Dotplot1DView = Base1DView.extend(self => {
13
+ const scaleFactor = observable.box(1)
14
+ return {
15
+ views: {
16
+ /**
17
+ * #getter
18
+ * this uses padding=false and elision=false
19
+ */
20
+ get dynamicBlocks() {
21
+ return calculateDynamicBlocks(self, false, false)
22
+ },
23
+ /**
24
+ * #getter
25
+ */
26
+
27
+ get scaleFactor() {
28
+ return scaleFactor.get()
29
+ },
30
+
31
+ /**
32
+ * #getter
33
+ */
34
+ get maxBpPerPx() {
35
+ return self.totalBp / (self.width - 50)
36
+ },
37
+
38
+ /**
39
+ * #getter
40
+ */
41
+ get minBpPerPx() {
42
+ return 1 / 50
43
+ },
44
+
45
+ /**
46
+ * #getter
47
+ */
48
+ get maxOffset() {
49
+ return self.displayedRegionsTotalPx - self.width * 0.2
50
+ },
51
+
52
+ /**
53
+ * #getter
54
+ */
55
+ get minOffset() {
56
+ return -self.width * 0.8
57
+ },
58
+ },
59
+ actions: {
60
+ /**
61
+ * #action
62
+ */
63
+ setScaleFactor(n: number) {
64
+ scaleFactor.set(n)
65
+ },
66
+
67
+ /**
68
+ * #action
69
+ */
70
+ center() {
71
+ const centerBp = self.totalBp / 2
72
+ const centerPx = centerBp / self.bpPerPx
73
+ self.scrollTo(centerPx - self.width / 2)
74
+ },
75
+ },
76
+ }
77
+ })
78
+
79
+ const DotplotHView = Dotplot1DView.extend(self => ({
80
+ views: {
81
+ get width() {
82
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ return getParent<any>(self).viewWidth
84
+ },
85
+ },
86
+ }))
87
+
88
+ const DotplotVView = Dotplot1DView.extend(self => ({
89
+ views: {
90
+ get width() {
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ return getParent<any>(self).viewHeight
93
+ },
94
+ },
95
+ }))
96
+
97
+ export { DotplotVView, DotplotHView, Dotplot1DView }
98
+ export type Dotplot1DViewModel = Instance<typeof Dotplot1DView>
@@ -0,0 +1,140 @@
1
+ type Func<T> = (value: BaseBlock, index: number, array: BaseBlock[]) => T
2
+
3
+ export class BlockSet {
4
+ constructor(public blocks: BaseBlock[] = []) {}
5
+
6
+ push(block: BaseBlock) {
7
+ if (block instanceof ElidedBlock && this.blocks.length > 0) {
8
+ const lastBlock = this.blocks.at(-1)
9
+ if (lastBlock instanceof ElidedBlock) {
10
+ lastBlock.push(block)
11
+ return
12
+ }
13
+ }
14
+
15
+ this.blocks.push(block)
16
+ }
17
+
18
+ getBlocks() {
19
+ return this.blocks
20
+ }
21
+
22
+ map<T, U = this>(func: Func<T>, thisarg?: U) {
23
+ // eslint-disable-next-line unicorn/no-array-method-this-argument
24
+ return this.blocks.map(func, thisarg)
25
+ }
26
+
27
+ forEach<T, U = this>(func: Func<T>, thisarg?: U) {
28
+ // eslint-disable-next-line unicorn/no-array-method-this-argument
29
+ return this.blocks.forEach(func, thisarg)
30
+ }
31
+
32
+ get length() {
33
+ return this.blocks.length
34
+ }
35
+
36
+ get totalWidthPx() {
37
+ return this.blocks.length
38
+ ? this.blocks.map(blocks => blocks.widthPx).reduce((a, b) => a + b)
39
+ : 0
40
+ }
41
+
42
+ get offsetPx() {
43
+ return this.blocks.length ? this.blocks[0].offsetPx : 0
44
+ }
45
+
46
+ get contentBlocks() {
47
+ return this.blocks.filter(block => block instanceof ContentBlock)
48
+ }
49
+ }
50
+
51
+ export class BaseBlock {
52
+ public reversed?: boolean
53
+
54
+ public refName: string
55
+
56
+ public start: number
57
+
58
+ public end: number
59
+
60
+ public assemblyName: string
61
+
62
+ public key: string
63
+
64
+ public widthPx = 0
65
+
66
+ public offsetPx = 0
67
+
68
+ /**
69
+ * a block that should be shown as filled with data
70
+ */
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ constructor(data: any) {
73
+ Object.assign(this, data)
74
+ this.assemblyName = data.assemblyName
75
+ this.refName = data.refName
76
+ this.start = data.start
77
+ this.end = data.end
78
+ this.key = data.key
79
+ }
80
+
81
+ /**
82
+ * rename the reference sequence of this block and return a new one
83
+ *
84
+ * @param refName -
85
+ * @returns either a new block with a renamed reference sequence,
86
+ * or the same block, if the ref name is not actually different
87
+ */
88
+ renameReference(refName: string) {
89
+ if (this.refName && refName !== this.refName) {
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
+ return new (this.constructor as any)({ ...this, refName })
92
+ }
93
+ return this
94
+ }
95
+
96
+ toRegion() {
97
+ return {
98
+ refName: this.refName,
99
+ start: this.start,
100
+ end: this.end,
101
+ assemblyName: this.assemblyName,
102
+ reversed: this.reversed,
103
+ }
104
+ }
105
+ }
106
+
107
+ export class ContentBlock extends BaseBlock {}
108
+
109
+ /**
110
+ * marker block representing one or more blocks that are
111
+ * too small to be shown at the current zoom level
112
+ */
113
+ export class ElidedBlock extends BaseBlock {
114
+ public widthPx: number
115
+
116
+ public elidedBlockCount = 0
117
+
118
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
+ constructor(data: Record<string, any>) {
120
+ super(data)
121
+ this.widthPx = data.widthPx
122
+ }
123
+
124
+ push(otherBlock: ElidedBlock) {
125
+ this.elidedBlockCount += 1
126
+
127
+ if (otherBlock) {
128
+ this.refName = ''
129
+ this.start = 0
130
+ this.end = 0
131
+ this.widthPx += otherBlock.widthPx
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * marker block that sits between two different displayed regions
138
+ * and provides a thick border between them
139
+ */
140
+ export class InterRegionPaddingBlock extends BaseBlock {}